2011-10-14 68 views
0

在此先感謝...正確,內存管理實現定製的NSDictionary吸氣劑

所以經過最近的一些內存泄漏和錯誤(記錄here),我已經在我的記憶管理學習了,我現在試圖在一個輔助類中爲NSDictionary編寫一個自定義getter。

自定義吸氣的原因是:

首先,這是一個計算的字典,所以對於性能問題,我想回到緩存的對象,除非有必要去重新創造它(我下面的例子是不是太耗費計算,但班上的其他人將是)。

二,我想懶洋洋地實例化。我只想在另一個類「請求」它時生成字典,這就是爲什麼我要在getter中檢查nil的原因。

所以,這些問題。下面的代碼代表我第一次(研究過)編寫自定義setter/getter的嘗試,我通常只是綜合。

1)這是正確的實施和適當的內存管理?

2)這是最好的嗎?

3)BOOL installedStandardsChangedSinceLastRead是否需要重新計算?如果課堂上的其他方法改變了某些東西,這將會發生。但是,我應該只是將這些方法清零_installedStandards,因爲這也會觸發重新計算?

4)最後,如果我確實只是有其他方法無法讓iVar標記它重新計算,我怎麼會確保我不泄漏?我會使用setter(即self.installedStandards = nil),直接不使用iVar(即_installedStandards = nil)還是其他?

(哦,如果我直接nil'd伊娃,我會需要先將它?這似乎是正確的將是[_installedStandards release]; _installedStandards = nil?在這種情況下,我不能只使用self.installedStandards = nil?)

在代碼上! 請注意,這是一個更復雜的類的簡化版本(請參閱頂部的鏈接),其中包含大量這些setters/getters。我需要確保我在執行之前正確執行。

.h文件中

@interface InstalledStandardTracker20 : NSObject { 

    NSDictionary *_installedStandards; 
    BOOL _installedStandardsChangedSinceLastRead; 
} 

@property (nonatomic, retain) NSDictionary *installedStandards; 
@property (nonatomic) BOOL installedStandardsChangedSinceLastRead; 

@end 

@implementation

@implementation InstalledStandardTracker20 

@synthesize installedStandardsChangedSinceLastRead = _installedStandardsChangedSinceLastRead; 

- (void)refreshInstalledStandards { 
    NSUserDefaults *currentDefaults = [NSUserDefaults standardUserDefaults]; 
    self.installedStandards = [currentDefaults objectForKey:@"installedStandards"]; 
    self.installedStandardsChangedSinceLastRead = NO; 
} 

- (NSDictionary *)installedStandards { 
    if (!_installedStandards || self.installedStandardsChangedSinceLastRead) { 
     [self refreshInstalledStandards]; 
    } 
    return _installedStandards; 
} 

- (void)setInstalledStandards:(NSDictionary *)newInstalledStandards { 
    [newInstalledStandards retain]; 
    [_installedStandards release]; 
    _installedStandards = newInstalledStandards; 
} 

回答

0

這個問題是比較難回答,因爲在課堂外沒有上下文。該代碼似乎是無內存泄漏。另外,您不需要實現-setInstalledStandards :.由於您在retain屬性上調用@synthesize,所生成的setter將看起來就像這樣。實質上,你用完全相同的方法覆蓋了該方法。

對於您的其他問題,剔除一個iVar與什麼對象被保存在內存中沒有任何關係。只要釋放iVar,指針中包含的內存地址處的對象就不再保證存在。通過消除iVar,您只需重置該內存地址即可指向零。這樣可以避免您獲得EXC_BAD_ACCESS運行時異常,因爲您的程序的其他部分不會嘗試訪問此時未定義的地址空間。

本質上,你總是要釋放它。雖然這是一種很好的做法,但只要您不知道該指針在內存中包含有效對象,就不會嘗試訪問該指針。我希望這是有道理的。

+0

感謝您的回覆。消除iVar是一種我認爲在下一次調用getter方法時強制進行重新計算的技術。無論如何,這是主意。如果某些東西發生了變化,我不會立即重新生成字典,而是將字典iVar清零,以便**如果再次調用getter,它將自動刷新。那有意義嗎?重點是懶惰地刷新iVar - 只有在再次調用getter時才重新計算。 – Murdock

+0

沒錯。你已經完成了你的懶加載。您不需要覆蓋setter,因爲該代碼默認存在。 – James

+0

有道理。早些時候,我收到了編譯器警告,說如果我重寫合成的iVar中的setter或getter中的任何一個,那麼我必須重寫這兩者。但我似乎沒有得到那個警告,所以... *聳聳肩* – Murdock