正确的,内存管理的自定义NSDictionary getter实现



Thanks in advance…

因此,在最近的一些内存泄漏和错误(记录在这里)之后,我一直在研究我的内存管理,我现在正试图在我的helper类中为NSDictionary编写一个自定义getter。

使用自定义getter的原因如下:

首先,它是一个计算过的字典,因此出于性能问题,我希望返回缓存的对象,除非有必要重新生成它(我下面的示例计算开销不是太大,但类中的其他示例会)。

第二,我想惰性实例化。我只想在另一个类"请求"它时生成字典,这就是为什么我在getter中检查nil的原因。

那么,这些问题。下面的代码代表了我第一次(研究)尝试编写自定义setter/getter,我通常只是合成。

1)这是正确的实现和正确的内存管理吗?

2)这样最好吗?

3) BOOL installedStandardsChangedSinceLastRead是标记需要重新计算的最佳方式吗?如果类中的其他方法改变了某些东西,就会发生这种情况。但我是否应该让这些方法nil输出_installedStandards,因为这也会触发重新计算?

4)最后,如果我只是有其他方法nil的iVar标记它重新计算,我如何确保我不泄漏?我会使用setter(即self.installedStandards = nil),直接nil iVar(即_installedStandards = nil),还是其他东西?

(哦,如果我直接nil了iVar,我需要先释放它吗?似乎正确的是[_installedStandards release]; _installedStandards = nil ?在这种情况下,我不能使用self.installedStandards = nil吗?)

到代码上! 提醒一下,这是一个简化版本,它将是一个更复杂的类(见顶部的链接),其中有很多这样的setter/getter。在我充实它之前,我需要确保我的执行是正确的。

. 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;
}

这个问题很难回答,因为在类之外没有上下文。代码似乎没有内存泄漏。此外,您不需要实现-setInstalledStandards:。由于在retain属性上调用@synthesize,因此生成的setter看起来就像这样。实际上,您是在用完全相同的方法重写该方法。

对于你的另一个问题,清空iVar与内存中保存的对象无关。一旦释放了iVar,指针中包含的内存地址处的对象就不再保证存在。通过对iVar赋空,您只需将该内存地址重置为指向nil。这样可以避免出现EXC_BAD_ACCESS运行时异常,因为程序的其他部分不会尝试访问这个现在未定义的地址空间。

本质上,你总是要释放它。虽然清空它是一种良好的做法,但只要您不尝试访问该指针,直到您知道它在内存中包含一个有效的对象,就不需要这样做。

最新更新