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运行时异常,因为程序的其他部分不会尝试访问这个现在未定义的地址空间。
本质上,你总是要释放它。虽然清空它是一种良好的做法,但只要您不尝试访问该指针,直到您知道它在内存中包含一个有效的对象,就不需要这样做。