2011-10-14 21 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