AVCam内存低警告

时间:2011-10-17 08:13:04

标签: xcode didreceivememorywarning avcam

这不是一个问题,更多的是我在Apple提供的针对iOS4和5相机操作提供的AVCam示例代码周围找到的内容的记录。问题的症状是我的应用程序在拍摄了大约5-10张照片后启动AVCamViewController时会崩溃。

我通过内存泄漏分析器运行应用程序并且没有明显泄漏但是在使用活动监视器进行检查时我发现每次启动摄像头时,称为mediaserverd的东西增加了17Mb,当它达到~100Mb时应用程序崩溃多个低内存警告。

3 个答案:

答案 0 :(得分:16)

我做的第一件事就是将登录记录到所有AVCam文件的dealloc方法中。我很快发现AVCamCaptureManager和AVCamRecorder在AVCamViewController时没有被释放。我检查了保留和释放调用,它们似乎达到了平衡,所以我在[captureManager release]上放了一个断点,发现它在发布后有一个retainCount为2(因此没有调用AVCamCaptureManager dealloc)。 / p>

接下来,我逐步完成了捕获管理器的创建过程,发现在调用init方法后,它的保留计数为3。

逐步执行init方法并检查每行的保留计数,我发现以下两行都增加了保留计数:

[self setDeviceConnectedObserver=[notificationCenter addObserverForName:AVCaptureDeviceWasConnectedNotification object:nil queue:nil usingBlock:deviceConnectedBlock]];
[self setDeviceDisconnectedObserver=[notificationCenter addObserverForName:AVCaptureDeviceWasDisconnectedNotification object:nil queue:nil usingBlock:deviceDisconnectedBlock]];

通过查看我发现removeObserver对应项是INSIDE的AVCamCaptureManager的dealloc方法(未被调用),因此保留计数从未降至0。

要修复它,我创建了一个新的公共removeObservers方法:

 -(void)removeObservers {
     NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
     [notificationCenter removeObserver:[self deviceConnectedObserver]];
     [notificationCenter removeObserver:[self deviceConnectedObserver]];
 }

并使用AVCamCaptureManager dealloc方法的相同行。

调用[captureManager removeObservers];然后调用[captureManager release];在AVCamViewController中,dealloc方法成功地将保留计数降为0。

现在,使用活动监视器进行测试时,mediaserverd进程仅在5-17Mb时嗡嗡作响,并且崩溃停止!

希望这可以帮助其他人解决这个问题!

答案 1 :(得分:4)

Apple在2013年10月17日修改了示例代码,修复了保留周期。问题是由于在self中定义的块中init使用不当。

这是修订说明

  

修复AVCaptureManager中导致泄漏的保留周期。 注意 - 如果您在应用中修改了AVCam代码,则应采用AVCaptureManager.m的{​​{1}}方法中的修补程序。如果没有这些修复,您可能会泄漏init个实例并在应用程序位于前台时让相机继续运行。


但是,它们引入的修复程序仅适用于手动保留计数。如果您在项目中使用ARC,除了摆脱AVCaptureManager / release调用和其他明显的事情外,retain的存储限定符必须从weakSelf更改到__block,如下。

__weak

事实上,__weak AVCamCaptureManager *weakSelf = self; 的语义随ARC而变化。在MRC中,它导致变量被弱引用,在ARC中它没有被引用,并且__block必须用于此目的。

有关此主题的更多信息,请访问:How do I avoid capturing self in blocks when implementing an API?

使用上一版本中的新__weak实施并使用init代替__weak,最终导致__block方法被正确调用。


最后,对于那些讨厌遗留旧代码的人来说,这是dealloc项目的现代化版本:https://github.com/Gabro/AVCam

特点:

  • 内存泄漏
  • 使用ARC
  • 现代Objective-C语法
  • iOS 7的小型UI修复

答案 2 :(得分:2)

最近遇到这个问题。我发现真正的根问题是deviceConnectedBlock和deviceDisconnectedBlock隐含地引用self,导致保留循环。要修复它,请更改这些块中的所有ivar引用以使用weakSelf。

这样,您就不需要记得明确地调用拆解方法。

希望这有助于其他人。

参考:View controller dealloc not called when using NSNotificationCenter code block method with ARC