【问题标题】:Proper, memory-managed implementation of custom NSDictionary getter自定义 NSDictionary getter 的正确的、内存管理的实现
【发布时间】:2011-12-07 09:29:50
【问题描述】:

提前谢谢...

所以在最近的一些内存泄漏和错误(记录在here)之后,我一直在研究我的内存管理,我现在正在尝试在我拥有的帮助器类中为 NSDictionary 编写自定义 getter。

自定义getter的原因是:

首先,它是一个计算字典,因此对于性能问题,我想返回缓存的对象,除非需要重新生成它(我下面的示例计算量不是很大,但类中的其他人会这样)。

其次,我想懒惰地实例化。我只想在另一个类“要求”时生成字典,这就是我在 getter 中检查 nil 的原因。

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

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

2) 这是最好的吗?

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

4) 最后,如果我 确实 只是让其他方法消除 iVar 以将其标记为重新计算,我将如何确保我不会泄漏?我会使用setter(即self.installedStandards = nil),直接nil iVar(即_installedStandards = 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;
}

【问题讨论】:

    标签: iphone ios memory-management getter-setter


    【解决方案1】:

    这个问题很难回答,因为课堂之外没有上下文。该代码似乎没有内存泄漏。此外,您不需要实现 -setInstalledStandards:。由于您在保留属性上调用 @synthesize,因此生成的设置器看起来就像那样。本质上,您使用完全相同的方法覆盖该方法。

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

    本质上,你总是必须释放它。虽然 nilling 是一种很好的做法,但只要您在知道它包含内存中的有效对象之前不尝试访问该指针,它就不是必需的。我希望这是有道理的。

    【讨论】:

    • 感谢您的回复。取消 iVar 是我认为我见过的一种技术,它可以在下次调用 getter 方法时强制重新计算。反正就是这个想法。如果发生更改,我不会立即重新生成字典,而是将 Dictionary iVar 设为 nil,以便再次调用 if getter,它将自动刷新。那有意义吗?关键是懒惰地刷新 iVar——只有在再次调用 getter 时才重新计算。
    • 对。您已经完成了延迟加载。您不需要覆盖 setter,因为该代码默认存在。
    • 有道理。早些时候,我收到编译器警告说,如果我在合成 iVar 中覆盖了 setter 或 getter 中的任何一个,那么我必须同时覆盖两者。但我似乎不再收到那个警告,所以... 耸耸肩
    猜你喜欢
    • 2017-07-26
    • 2023-03-29
    • 2011-09-20
    • 2011-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-10
    相关资源
    最近更新 更多