AVCam内存低警告

Red*_*ale 7 xcode didreceivememorywarning avcam

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

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

Red*_*ale 16

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

接下来,我逐步完成了捕获管理器的创建过程,发现在调用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]];
Run Code Online (Sandbox Code Playgroud)

通过浏览我发现removeObserver对应物是INSIDE的AVCamCaptureManager的dealloc方法(它没有被调用),所以保留计数从未下降到0.

为了解决这个问题,我创建了一个新的公共removeObservers方法:

 -(void)removeObservers {
     NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
     [notificationCenter removeObserver:[self deviceConnectedObserver]];
     [notificationCenter removeObserver:[self deviceConnectedObserver]];
 }
Run Code Online (Sandbox Code Playgroud)

并使用相同的行OUT AVCamCaptureManager dealloc方法.

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

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

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


Gab*_*lla 4

Apple 于 2013 年 10 月 17 日修改了示例代码,修复了保留周期。self该问题是由于init.

这是修订说明

AVCaptureManager修复了导致泄漏的保留周期。注意- 如果您在应用程序中调整了代码,则应该采用 的方法AVCam中进行的修复。如果没有这些修复,您可能会泄漏实例并让相机在您的应用程序位于前台时持续运行。AVCaptureManager.minitAVCaptureManager


然而,他们引入的修复仅适用于手动保留计数的情况。如果您在项目中使用 ARC,除了摆脱release/retain调用和其他明显的事情之外,还必须将 的存储限定符weakSelf从 更改__block__weak,如下所示。

__weak AVCamCaptureManager *weakSelf = self;
Run Code Online (Sandbox Code Playgroud)

事实上__blockARC 的语义发生了变化。在 MRC 中,它会导致变量被弱引用,而在 ARC 中则不会,并且__weak必须用于此目的。

有关此主题的更多信息可以在此处找到:实现 API 时如何避免在块中捕获 self?

init使用上次修订中的新实现并使用__weak而不是__block,最终导致该dealloc方法被正确调用。


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

特征:

  • 无内存泄漏
  • 使用ARC
  • 现代 Objective-C 语法
  • 针对 iOS 7 的细微 UI 修复