2011-10-17 51 views
7

這不是一個問題,更多的是我發現蘋果iOS4和5相機操作提供的AVCam示例代碼的記錄。對我來說,問題的症狀是我的應用程序會在拍攝5-10張照片後啓動AVCamViewController時崩潰。AVCam內存低警告

我通過內存泄漏分析器運行了應用程序,但沒有發現明顯的泄漏,但通過活動監視器檢查發現,每次啓動攝像頭並且達到〜100Mb應用程序時,稱爲mediaserverd的內容都會增加17Mb多次低內存警告墜毀。

+0

謝謝!請把答案分成一個答案,然後你可以接受:[回答你自己問題的禮節](http://meta.stackexchange.com/questions/17845/etiquette-for-answering-your-own-question)和[發佈和回答你已經找到答案的問題](http://meta.stackexchange.com/questions/2706/posting-and-answering-questions-you-have-already-found-the-answer-to) – sehe

+0

嘗試過,但因爲我不是高級用戶,它不會讓我在24小時內回答我自己的問題......沒有時間來解決它(或忘記我想要錄製的內容)......我會看看我現在能否做到。 –

回答

4

蘋果訂正年10月17 2013示例代碼,固定保持週期。這個問題是由於init中定義的塊內self的使用不當造成的。

這裏的修訂說明

固定保留AVCaptureManager導致泄漏週期。 注意 - 如果您已在自己的應用中修改了AVCam代碼,則應採用此處修復的方法,其格式爲AVCaptureManager.minit方法。如果沒有這些修復程序,您可能會泄漏AVCaptureManager實例,並且在您的應用處於前臺時讓相機不斷運行。


然而,他們推出了補丁只能在手冊的情況下,保留計數。如果您在項目中使用ARC,除了擺脫release/retain來電和其他明顯的事情外,weakSelf的存儲限定符必須從__block更改爲__weak,如下所示。

__weak AVCamCaptureManager *weakSelf = self; 

事實上語義的__block改變與ARC。在MRC中,它導致變量被弱引用,在ARC中它不是必須的,並且__weak必須用於此目的。關於這個話題

更多信息可以在這裏找到:How do I avoid capturing self in blocks when implementing an API?

使用從最後一次修訂的新init實施和使用__weak代替__block,最終導致被正確地稱爲dealloc方法。


最後,對於那些誰不喜歡隨身攜帶舊的遺留代碼,這裏的AVCam項目的現代版:https://github.com/Gabro/AVCam

特點:

  • 內存泄漏免費
  • 使用ARC
  • 現代Objective-C語法
  • minor UI修復iOS 7
+0

嗨加布裏埃,我看了一下你的AVCam項目。您可能會將「ARC兼容」評論更改爲「ARC獨家」?我已經將它添加到我的非ARC項目中,並且存在與使用ARC專有功能相關的一些編譯失敗。 –

+0

@RedNightingale絕對是,可怕的話選擇。順便說一下,如果你願意,即使在非ARC項目中,你也可以選擇性地啓用特定文件上的ARC。希望能幫助到你。 –

+0

我會研究一下。已經嘗試了Apple代碼的新版本,他們似乎終於正常工作,所以我會推動這是答案。 –

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]]; 

翻翻我發現removeObserver同行在裏面dealloc方法在AVCamCaptureManager(這是不會被調用),並因此保留計數從未下降到0

要解決它,我創建了一個新的公共removeObservers方法:

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

並採用與AVCamCaptureManager dealloc方法相同的方法OUT。

調用[captureManager removeObservers];然後調用[captureManager release];在AVCamViewController中,dealloc方法成功地將保留計數降爲0.

使用活動監視器進行測試現在mediaserverd進程只有5-17Mb的嗡嗡聲,並且崩潰停止!

希望這可以幫助任何人有這個問題!

+1

更好...強大的SO神允許我現在回答我自己的問題;) –

+0

強大的SO神允許我通過給予我+1來表示感謝;) – sehe

+0

好的描述。我相信我們遇到了同樣的問題。 –

2

最近碰到這個問題。我發現真正的根本問題是deviceConnectedBlock和deviceDisconnectedBlock隱含地指自己,導致保留週期。要修復它,請更改這些塊中的所有ivar引用以使用weakSelf。

這樣,您不需要明確地調用拆卸方法。

希望這可以幫助別人。

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

+0

我確實有一個參考自我在該塊。我用weakSelf取而代之,然後恢復到'正常'AVCAM發佈代碼。 CaptureManager仍然沒有調用dealloc。您鏈接的文章引用__weak作爲參考,但是這僅適用於ARC代碼(我目前不使用)。我需要使用__block來代替,但是對「塊」的理解不夠充分,無法提出可用的等效解決方案。 –