我是否应该在分配到保留属性时保留自动释放的对象?

时间:2011-02-21 05:49:58

标签: iphone objective-c properties retain autorelease

在我保留的某个属性的getter中,我为我的模型对象(“models”)分配并分配了一个NSArray。然后我使用“sortedArrayUsingSelector:”方法对NSArray进行排序。根据文档,这将返回一个自动释放的NSArray。然后我将其重新分配给我的“模型”数组。

起初,我从未保留过这个自动释放的排序数组,并发现当我将此viewController从堆栈中弹出时,我的应用程序会崩溃,说我试图减少已释放对象或类似内容的引用计数。然后我在下面的代码中添加了一个retain,一切都没问题。

我的问题是,这是正确的,我应该保留自动释放的对象,即使我在其声明中保留此属性并在我的dealloc中释放它?

- (NSArray *)models {

    if (!models) {
        models = [[NSArray alloc] initWithArray:[self.modelDictionary allKeys]];
        models = [[models sortedArrayUsingSelector:@selector(compare:)] retain];
    }
    return models;

}

3 个答案:

答案 0 :(得分:7)

一般来说,如果你想要一个自动释放的对象,你必须retain它。

此代码存在以下几个问题:

- (NSArray *)models {

    if (!models) {
        models = [[NSArray alloc] initWithArray:[self.modelDictionary allKeys]];
        models = [[models sortedArrayUsingSelector:@selector(compare:)] retain];
    }
    return models;
}
  • 您使用第二行alloc/init代码泄露了models= d的数组

  • 你说“在声明中保留了这个属性,但在上面的代码中,你直接分配给实例变量,绕过了@synthesize

    <可能生成的setter方法/ LI>
  • 它是一个getter方法,可以改变所获得变量的状态......虽然这种延迟初始化很有吸引力,但必须非常小心。核心数据经历了相当长的内部复杂性,以这种方式允许懒惰的国家群体。上面的代码也意味着models属性的键值观察者在执行getter时不会看到更改。但是,如果您从getter手动调用willChangeValueForKey:/didChangeValueForKey:,您最终会在getter内发送更改通知,很可能会导致某些内容消耗之前的值 whoever调用getter首先检索值。声音混乱?它是 - 可能会或可能不会导致问题。根据我的经验,有一天可能会引起问题。


一些建议:

  • 如果可以,请使用核心数据。为了使Core Data非常高效并与系统完美集成,我们投入了大量的工程工作。

  • 将getter / setter与其余逻辑分开。更有可能的是,您的应用程序中有一个逻辑点,您需要“获取”模型。当你这样做时,通过其他方法告诉对象故障,然后获取模型。这可能看起来很痛苦,但是对象图的构造非常专业,而不是查询该图以获取信息(或者使用Core Data,它有解决方案)。

答案 1 :(得分:1)

除非我遗漏了某些内容,否则您只是将结果设置为某个实例变量。我认为您应该使用您的属性。

self.models =  [NSArray arrayWithArray:[self.modelDictionary allKeys]];

没有self.部分,您没有使用setter方法,因此从不保留任何内容。

答案 2 :(得分:0)

谢谢!我明白你的意思。我想我很困惑,并认为在我的getter中调用self.models会创建一个无限循环。我现在看到,只是我从getter中调用getter而不是getter中的setter。我把我的代码更改为:

- (NSArray *)models {
    if (!models) {
        self.models = [[NSArray alloc] initWithArray:[self.modelDictionary allKeys]];
        self.models = [models sortedArrayUsingSelector:@selector(compare:)];
    }
    return models;
}

一切都可以编译并正常工作......这看起来是一个更正确的解决方案吗?谢谢你的时间。