MPMoviePlayerController 在视图展开到全屏时释放

Posted

技术标签:

【中文标题】MPMoviePlayerController 在视图展开到全屏时释放【英文标题】:MPMoviePlayerController deallocated when view is expanded to FullScreen 【发布时间】:2012-10-02 02:39:16 【问题描述】:

如何检查MPMoviePlayerController 的实例何时被释放?请注意,我已经将 NSZombieEnabled 设置为 YES 并进行了检查。

有问题的代码在我的应用中的某些情况下运行良好。在另一种情况下,当带有moviePlayer 控件的视图展开时,MPMoviePlayerDidEnterFullscreenNotification 回调方法会在屏幕变黑并且从用户角度看应用冻结后不久执行。 (不同的是这个在导航堆栈上有一个额外的 viewController)。它不会使应用程序崩溃。它仍在运行,但无法返回可用的 UI。

在调试器中,我检查实例“活动”的最后已知时间以获取其地址,检查并发现它已被释放:

2012-10-01 18:35:46.032 MyApp[930:907] -[MyMoviePlayerViewController moviePlayerDidEnterFullscreenNotification:](203): : moviePlayer = <MPMoviePlayerController: 0x1dba9420> loadState = 3
2012-10-01 18:36:05.280 MyApp[930:907] [MPAVController] Autoplay: Enabling autoplay

这里出现黑屏,所以我检查调试器:

(lldb) po 0x1dba9420
2012-10-01 18:37:38.656 MyApp[930:907] *** -[MPMoviePlayerController respondsToSelector:]: message sent to deallocated instance 0x1dba9420
(int) $0 = 498766880 [no Objective-C description available]

如果我检查其他类的其他已知实例,它们是活着的并且如预期的那样:

(lldb) po 0x1da12110
(int) $1 = 497099024 <MyDetailViewControllerWithTableView: 0x1da12110>
(lldb) po 0x1da1af70
(int) $2 = 497135472 <MyMasterTableViewController: 0x1da1af70>
(lldb) po 0x1da19be0
(int) $3 = 497130464 <NSFetchedResultsController: 0x1da19be0>

所以,重申一下,如何检查实例何时以及通过什么方式被释放或销毁?是否有可以使用的 Instruments 类型。 Allocations 显示实例已分配,但现在不存在了....

我想我可以逐步跟踪,但这很乏味... 能够在事件发生并触发时设置条件会很棒 Instruments(或调试器)停止。

【问题讨论】:

Instruments:Allocation 中的一些额外调查显示 MyMoviePlayerController 是由 MyAddDetailViewController 分配的 Malloc,由 (UIKit) -[UIViewController dealloc] 释放。 MyAddDetailViewController 在 MyAddDetailViewController 被释放前几毫秒被 (UIKit) -[UIClassSwapper initWithCoder] 和 (UIKit) -[UIViewController dealloc] 释放。所以现在,我知道了答案,但不是根本原因。 看起来 MyAddDetailViewController 由于 AutoreleasePoolPage 而被释放,这表明我的代码破坏了对它的强引用(项目使用 ARC)。 【参考方案1】:

我解决了这个问题。似乎当用户展开moviePlayer时,事件生命周期导致视图(MyAddDetailViewController)(持有子视图(MyMoviePlayerController))执行viewWillDisappear和viewDidDisappear。

我提到代码路径在导航堆栈上创建了一个额外的 viewController,并且 VC 正在短暂出现(由 viewWillAppear 消息证明)然后返回后台并使用 viewWillDisappear。目前还不清楚为什么这会导致 autoreleasePool 释放 MyAddDetailViewController 从而释放 MyMoviePlayerController,但现在很清楚没有对 MyAddDetailViewController 的强引用。

为了解决这个问题,我在 VC 中创建了一个属性,将 MyAddDetailViewController 推送到导航堆栈上以保持对它的强引用。

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender

// ... snip ...
    self.myAddDetailViewControllerReference = [segue destinationViewController];



//

- (void)viewDidUnload 
    [self setMediaAddDetailViewControllerReference:nil];


这可以解决黑屏/冻结问题。

【讨论】:

以上是关于MPMoviePlayerController 在视图展开到全屏时释放的主要内容,如果未能解决你的问题,请参考以下文章

如何在 MPMoviePlayerController 上处理多个 SRT 文件

在 MPMoviePlayerController 上执行捏合手势时屏幕黑屏

在 UITableViewCell 中嵌入 MPMoviePlayerController

MPMoviePlayerController 在影片结尾更改控件样式

后台的 MPMoviePlayerController / AVAudioSession 在来电后不会重新开始播放

MPMoviePlayerController 在启动前显示空白屏幕?