Я пытаюсь создать приложение, которое воспроизводит видео из файла с помощью AVFoundation
. Видеоролики отображаются в виде, доступ к которому осуществляется нажатием на строку в родительском представлении таблицы. У реального приложения будет видео для каждой строки, но на данный момент я использую только один для тестирования.
При запуске на симуляторе приложение работает нормально, но при запуске на устройстве (под ios 5.1) видео воспроизводится нормально примерно в 5 раз, а затем непредсказуемо разбивается по множеству способов.
Чаще всего видеозагрузка загружается, но само видео не воспроизводится, но иногда
Я получаю EXC_BAD_ACCESS
в потоке coremedia.remote
, жалуясь на объекты, которые выделяются без пула авторезистов. Я добавил блок @autoreleasepool
, обертывающий код, запускающий AVPlayer, но это, похоже, не помогает.
Мне интересно, происходит ли GCD, создавая несколько потоков в главной очереди для воспроизведения элементов, но они не заканчиваются.
Итак, ключевой вопрос - как я могу очистить лишние потоки GCD, на которых работает AVPlayer?
если пользователь нажимает кнопку "Назад" в режиме просмотра видео
Насколько это возможно, я следовал примеру кода, представленного в документации Apple AVFoundation
здесь
Я добавил несколько протоколов и (как упоминалось выше) блок @autoreleasepool
внутри одного из блоков GCD, кроме того, что я не изменил код.
Метод viewDidLoad
выглядит следующим образом:
-(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 tracks were not loaded");
}
}
});
}];
}
Метод viewWillDisappear
:
-(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");
});
}
Я боролся с этим в течение большей части сегодняшнего дня - любая помощь была бы с благодарностью принята