多次播放后AVPlayer崩溃 - [英] AVPlayer crashes after multiple playbacks-

查看:105
本文介绍了多次播放后AVPlayer崩溃 - 的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 AVFoundation 创建一个播放文件视频的应用。视频显示在通过点击父表视图中的行访问的视图中。真正的应用程序将为每一行都有一个视频,但目前我只使用一个进行测试。



在模拟器上运行时应用程序没问题,但是当在设备上运行时(在ios 5.1下),视频可以播放大约5次,然后以各种方式无法预测地崩溃。
最常见的是,视频视图加载但视频本身无法播放,但有时
我在 EXC_BAD_ACCESS > coremedia.remote thread,抱怨分配的对象没有自动释放池。我添加了一个 @autoreleasepool 块来包装启动AVPlayer的代码,但这似乎没什么帮助。



<我想知道发生的事情是GCD是在主队列上创建多个线程来播放这些项目,但它们并没有终止。



所以关键问题是 - 如果用户点击视频视图中的后退按钮,如何清除AVPlayer在
上运行的多余GCD线程
我尽可能地遵循Apple提供的示例代码 AVFoundation 文档这里
我添加了一些日志记录和(如上所述)一个GCD块内的 @autoreleasepool 块 - 除此之外我还没有没有改变代码。



viewDidLoad 方法如下:

   - (void)viewD idLoad {
[super viewDidLoad];

NSURL * fileURL = [[NSBundle mainBundle] URLForResource:@TestLapCar2VidwithExtension:@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(@资产加载);
[avPlayer play];
}
else {
NSLog(@资产的轨道未加载);
}

}
});
}];

}



viewWillDisappear 方法是:

   - (void)viewWillDisappear:(BOOL)animated {
NSLog(@视图将消失称为);
[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有%d个子控制器,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(@release stuff);
});

}



我一直在苦苦挣扎对于今天的大部分时间都是这样 - 任何帮助都会感激不尽

解决方案

你应该先从superview中删除,因为它会减少保留数量为1,ARC将负责您的代码的发布。



喜欢这个

  [videoView removeFromSuperview]; 
[self setVideoView:nil];


I'm trying to create an app which plays videos from a file using AVFoundation. The videos are shown in a view accessed by tapping on a row in a parent tableview. The real app will have a video for each row, but at the moment I'm using just one for testing.

When run on the simulator the app is ok, but when run on the device (under ios 5.1) the video plays ok for about 5 times, then crashes unpredictably in a variety of ways. Most commonly, the video view loads but the video itself doesn't play, but sometimes I get an EXC_BAD_ACCESS on a coremedia.remote thread, complaining about objects being allocated with no autorelease pool in place. I've added an @autoreleasepool block wrapping the code launching the AVPlayer, but this doesn't seem to help.

I'm wondering whether what is happening is that GCD is creating multiple threads on the main queue to play the items, but they are not terminating.

So the key question is- how do I clear up the superfluous GCD threads the AVPlayer is running on if the user hits the back button in the video view As far as possible I've followed the example code provided in Apple's AVFoundation documentation here I've added some logging and (as mentioned above) an @autoreleasepool block inside one of the GCD blocks- other than that I haven't changed the code.

The viewDidLoad method is as follows:

-(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");
             }

         }
     });
 }];    

}

The viewWillDisappear method is:

-(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");
    });

}

I've been struggling with this for most of today- any help would be gratefully received

解决方案

You should remove from superview first as it will reduce the retain count by 1 and ARC will take care of the release for your code.

like this

[videoView removeFromSuperview];
[self setVideoView:nil];

这篇关于多次播放后AVPlayer崩溃 - 的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆