2014-01-27 32 views
0

我在ARC下有一個tableview控制器,用於從每個顯示的tableview單元的地址簿中讀取數據。由於性能方面的原因,我無法打開每個撥打tableView:cellForRowAtIndexPath:的地址簿,我在viewDidLoad中打開一次,並將它的引用存儲在@property (nonatomic) ABAddressBookRef addressBookRef;中。它將在012view中以dealloc的方式發佈在桌面視圖控制器中。
這在我看來是正確的,但靜態分析訴說viewDidLoad關於「對象的潛在泄漏」在下面的if語句的行:iOS:如何在不存在「潛在泄漏」警告的情況下將ABAddressBookRef存儲在屬性中?

- (void)viewDidLoad{ 
    [super viewDidLoad]; 
    CFErrorRef error = nil; 
    self.addressBookRef = ABAddressBookCreateWithOptions (NULL, &error); 
    if (self.addressBookRef == nil) { 
     NSLog(@"%@: %@: Could not open addressbook", NSStringFromClass([self class]), NSStringFromSelector(_cmd)); 
    } 

...

待辦事項我有什麼不對,或者我怎麼能擺脫這個警告?

回答

0

您可以覆蓋setAddressBookRef:,使其保留地址簿引用,並在分配屬性後釋放它。

就是這樣。你會想檢查NULL,因爲調用CFRetain/Release會導致運行時錯誤。

- (void)setAddressBookRef:(ABAddressBookRef)addressBook 
{ 
    CFRetain(addressBook); 
    CFRelease(_addressBookRef); 
    _addressBookRef = addressBook; 
} 
+0

感謝您的回答,但我完全無法理解它:在我看來,問題並非保留/釋放的錯誤處理。 ABAddressBookCreateWithOptions創建一個保留計數爲1的CF對象,並通過dealloc中的CFRelease進行平衡。問題似乎是靜態分析器不知道最終會調用dealloc,所以沒有內存會泄漏。在OSX下,可能會將CF對象連接到NS對象,以便ARC可以處理它。但這在iOS中是不可能的。 –

+0

通常情況下,你會希望你的setter保留這個對象,這會在保留數量增加到兩個之前,然後你自己釋放它,這會降低到一個。當它在dealloc中釋放時,它會降到零。如果你有一個Objective-C對象的'strong'屬性,那麼它就是爲你做的。 – Collin

+0

我試過你的解決方案,它的工作原理是,如果地址簿是由CFRelease(_addressBookRef)在dealloc中發佈的。再次感謝! –

1

我相信我找到了解決辦法,雖然我不是100%肯定的:
我宣佈,存儲地址簿引用作爲

@property (strong, nonatomic) id addressBookRef; 

財產,受

分配對它的引用
self.addressBookRef = CFBridgingRelease(ABAddressBookCreateWithOptions (NULL, &error)); 

這應該將所有權從CF轉移到ARC。
在我的代碼,無論我訪問地址薄參考,我把它用

(__bridge ABAddressBookRef)(self.addressBookRef) 

而且由於保留/釋放,現在由ARC處理做,在dealloc方法的CFRelease(self.addressBookRef)不再是必要的。
編譯器警告消失了!