2010-12-05 57 views
2

我當時正在泄漏的工具內存泄漏,發現在我的字典mutableDeepCopy大規模的泄漏,但我無法弄清楚什麼是錯的代碼。有什麼建議麼?無法弄清楚如何解決在iPhone上

@interface RootViewController : UIViewController{ 

    NSDictionary *immutableDictionary; 
    NSMutableDictionary *mutableDictionary; 
} 

下面是在儀器突出的代碼行

self.mutableDictionary = [self.immutableDictionary mutableDeepCopy]; 

以下是創建一個字典

@interface NSDictionary(MutableDeepCopy) 
    -(NSMutableDictionary *)mutableDeepCopy; 
@end 

這裏的一個可變副本的方法方法實現,我已經強調了泄漏SAIDS代碼正在泄漏100%

- (NSMutableDictionary *) mutableDeepCopy { 
    NSMutableDictionary *dictionaryToReturn = [NSMutableDictionary dictionaryWithCapacity:[self count]]; 
    NSArray *keys = [self allKeys]; 

    for(id key in keys) { 
     id value = [self valueForKey:key]; 
     id copy = nil; 
     if ([value respondsToSelector:@selector(mutableDeepCopy)]) { 
      copy = [value mutableDeepCopy]; 
     } else if ([value respondsToSelector:@selector(mutableCopy)]) { 
      copy = [value mutableCopy]; //This is the Leak 
     } 
     if (copy == nil) { 
      copy = [value copy]; 
     } 
     [dictionaryToReturn setValue:copy forKey:key]; 
    } 
    return dictionaryToReturn; 
} 
+0

與問題無關,但您應該使用objectForKey:/ setObject:forKey:而不是valueForKey:/ setValueForKey:後者實際上是爲KVC設計的,雖然他們在NSDictionary上做了幾乎相同的事情,但他們這樣做更緩慢且具有細微的差異。 – JeremyP 2010-12-05 22:22:23

+0

感謝您的提示Jeremy – aahrens 2010-12-05 22:52:08

回答

3

你需要分析這個蘋果的Memory Management Rules的光。

這一行開始:

self.mutableDictionary = [self.immutableDictionary mutableDeepCopy]; 

我希望mutableDeepCopy返回一個對象我自己,所以在某些時候我需要釋放或自動釋放它。例如

NSMutableDeepCopy* temp = [self.immutableDictionary mutableDeepCopy]; 
self.mutableDictionary = temp; 
[temp release]; 

self.mutableDictionary = [[self.immutableDictionary mutableDeepCopy] autorelease]; 

所以現在我們需要看看mutableDeepCopy。因爲它的名字需要「複製」,所以它需要返回一個「擁有」對象,實際上意味着「忘記」釋放返回的對象。由於dictionaryWithCapacity:給你一個你不擁有的對象,所以當你在第一行創建返回對象時,你已經失敗了。將其替換爲

NSMutableDictionary *dictionaryToReturn = [[NSMutableDictionary alloc] initWithCapacity:[self count]]; 

現在你擁有它。

讓你的mutableDeepCopy服從規則是很重要的,因爲這意味着你可以將mutableDeepCopy,mutableCopy返回的對象以完全相同的方式處理。在所有三種情況下,您擁有插入到數組中的對象副本。因爲你擁有它,所以你必須釋放它,否則它會在你發現的時候泄漏。因此,在循環結束時,您需要

[copy release]; 

這樣可以阻止泄漏。

2

mutableCopy遞增對象的保留計數一樣,setValue:forKey:。這意味着,當dictionaryToReturn被dealloc'ed,即有mutableCopy對象調用仍然有一個的保留計數。

嘗試這樣做,而不是:

copy = [[value mutableCopy] autorelease]; 
+0

這似乎工作,但現在當我運行儀器應用程序崩潰時,當我試圖執行該代碼。但是,當我剛剛使用該應用程序時,我還沒有看到任何崩潰。 – aahrens 2010-12-05 22:07:40

+0

奇數。請記住(與Eiko提到的一樣),名稱中帶有「copy」字樣的方法應返回保留計數爲+1的對象。 mutableCopy和複製已經做了,但你的mutableDeepCopy方法沒有。相應地調整方法變量和返回對象的內存管理,並再次調用它。 – 2010-12-05 22:13:54

3

如何你的財產申報?如果是retaincopy,那麼這不會泄漏。

您的問題是,這個名字mutableDeepCopy表明,它返回一個對象保留,而不是一個自動釋放的一個,因爲它實際上做。

編輯: 並在mutableDeepCopy本身,你需要添加到字典後釋放copy變量。