AVPlayer ulega awarii po wielokrotnym odtwarzaniu -

Próbuję utworzyć aplikację, która odtwarza filmy z pliku za pomocąAVFoundation. Filmy są wyświetlane w widoku, do którego można uzyskać dostęp, dotykając wiersza w widoku tabeli nadrzędnej. Prawdziwa aplikacja będzie miała wideo dla każdego wiersza, ale w tej chwili używam tylko jednego do testowania.

Po uruchomieniu na symulatorze aplikacja jest w porządku, ale po uruchomieniu na urządzeniu (pod ios 5.1) wideo jest odtwarzane ok. 5 razy, a następnie nieprzewidywalnie ulega awarii na wiele sposobów. Najczęściej ładuje się widok wideo, ale sam film nie gra, ale czasami dostajęEXC_BAD_ACCESS nacoremedia.remote wątek, narzekający na obiekty przydzielane bez puli autorelease. Dodałem@autoreleasepool zablokuj zawijanie kodu uruchamiającego AVPlayera, ale to chyba nie pomaga.

Zastanawiam się, czy dzieje się tak, że GCD tworzy wiele wątków w głównej kolejce, aby odtwarzać przedmioty, ale nie kończą się.

Kluczowym pytaniem jest więc, jak wyczyścić zbędne wątki GCD, na których działa AVPlayer, jeśli użytkownik kliknie przycisk Wstecz w widoku wideo. O ile to możliwe, zastosowałem przykładowy kod podany w AppleAVFoundation dokumentacjatutaj Dodałem trochę logowania i (jak wspomniano powyżej) i@autoreleasepool zablokuj wewnątrz jednego z bloków GCD - poza tym nie zmieniłem kodu.

TheviewDidLoad metoda jest następująca:

<code>-(void)viewDidLoad{   
[super viewDidLoad];

NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"TestLapCar2Vid" withExtension:@"m4v"];
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:fileURL options:nil];
NSString *tracksKey = @"tracks";

[asset loadValuesAsynchronouslyForKeys:[NSArray arrayWithObject:tracksKey] completionHandler:
 ^{
     dispatch_async(dispatch_get_main_queue(),
     ^{
         @autoreleasepool {
         NSError *error = nil;
             AVKeyValueStatus status = [asset statusOfValueForKey:tracksKey error:&error];

             if(status == AVKeyValueStatusLoaded){
                 avPlayerItem = [AVPlayerItem playerItemWithAsset:asset];
                 [avPlayerItem addObserver:self forKeyPath:@"status"
                                   options:0  context:&ItemStatusContext];

                 [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(playerItemDidReachEnd:)
                                                             name:AVPlayerItemDidPlayToEndTimeNotification object:avPlayerItem];

                 avPlayer = [AVPlayer playerWithPlayerItem:avPlayerItem];
                 [videoView setPlayer:avPlayer];
                 NSLog(@"Asset loaded");
                 [avPlayer play];
             }
             else{
                 NSLog(@"The asset's tracks were not loaded");
             }

         }
     });
 }];    
</code>

}

TheviewWillDisappear metoda to:

<code>-(void)viewWillDisappear:(BOOL)animated{
NSLog(@"view will disappear called");
[super viewWillDisappear:animated];
dispatch_async(dispatch_get_main_queue(), 
    ^{
        [avPlayer pause];
        [avPlayerItem removeObserver:self forKeyPath:@"status"];
        [[NSNotificationCenter defaultCenter]removeObserver:self];
        NSLog(@"Race timeline nav controller has %d sub controllers",self.navigationController.childViewControllers.count);
        avPlayerItem = nil;
        avPlayer = nil;
        videoView = nil;
        dataStore = nil;
        pkReader = nil;
        receivedData = nil;
        revDial = nil;
        speedDial = nil;
        mapView = nil;
        throttle = nil;
        NSLog(@"releasing stuff");
    });
</code>

}

Przez większość dnia zmagałem się z tym - każda pomoc byłaby wdzięczna

questionAnswers(2)

yourAnswerToTheQuestion