fellow StackOverflow user告诉我,在发布属性时我不应该使用getter方法:
@property(nonatmic, retain) Type* variable;
@synthesize variable;
// wrong
[self.variable release];
// right
[variable release];
他没有详细解释原因。它们看起来和我一样。 My iOS book说房产的吸气剂看起来像这样:
- (id)variable {
return variable;
}
那么这是不是意味着[self variable]
,self.variable
和variable
都是一样的?
答案 0 :(得分:13)
对于没有自定义访问者的保留属性,您可以通过以下方式释放对象:
self.variable = nil;
这具有将ivar(如果只声明属性可能不被称为'变量')设置为nil并释放先前值的效果。
正如其他人所指出的那样,要么直接释放ivar(如果可用),要么使用上面的方法就可以了 - 你不能做的就是从getter返回的变量上调用release。
答案 1 :(得分:9)
您可以选择编写自定义getter行为,这可能会导致完全不同的行为。因此,您不能总是假设[variable release]
与[self.variable release]
具有相同的结果。
同样,您可以编写自定义属性,而无需使用独有的ivar支持它们......如果您开始从getter返回的引用中释放对象,它可能会变得很乱!
可能还有其他原因让我不知道......
答案 2 :(得分:4)
典型的吸气剂看起来更像是这样:
- (id)variable {
return [[variable retain] autorelease];
}
因此,如果您使用[self.variable release]
,那么当您只想释放该对象并导致该对象被释放时,您还需要一个额外的retain
和autorelease
迟于必要时(自动释放池耗尽时)。
通常情况下,您可以使用self.variable = nil
,这样做的好处是它还可以将变量设置为nil
(避免因悬空指针而导致崩溃),或者[variable release]
这是最快的如果您的setter具有自定义逻辑,则可能更适合dealloc
方法。
答案 3 :(得分:4)
并非所有的吸气者都采用这种形式:
- (id)variable { return variable; }
......这只是最原始的形式。单独的属性应该建议更多的组合,这会改变实现。上面的原始访问器不考虑与内存管理,原子性或复制语义一起使用的习语。在子类覆盖中,实现也很脆弱。
以下是一些非常简短的例子;在实际程序变得相当复杂的实际程序中,事情显然变得更加复杂。
1)getter可能不会返回实例变量。几种可能性之一:
- (NSObject *)a { return [[a copy] autorelease]; }
2)setter可能不会保留实例变量。几种可能性之一:
- (void)setA:(NSObject *)arg
{
...
a = [arg copy];
...
}
3)您最终在整个程序中实施内存管理,这使得维护变得困难。应该将类的语义(以及它如何处理实例变量的引用计数)保存到类中,并遵循预期结果的约定:
- (void)stuff:(NSString *)arg
{
const bool TheRightWay = false;
if (TheRightWay) {
NSMutableString * string = [arg mutableCopy];
[string appendString:@"2"];
self.a = string;
[string release];
// - or -
NSMutableString * string = [[arg mutableCopy] autorelase];
[string appendString:@"2"];
self.a = string;
}
else {
NSMutableString * string = [arg mutableCopy];
[string appendString:@"2"];
self.a = string;
[self.a release];
}
}
未能遵循这些简单的规则会使您的代码难以维护和调试,并且难以扩展。
所以缺点是你想让你的程序易于维护。直接在属性上调用release需要您知道该类内部工作的大量上下文;这显然很糟糕,并且错过了良好的OOD的强烈理想。
它还希望作者/子类/客户确切地知道类如何偏离惯例,这在问题出现时是愚蠢和耗时的,并且当问题出现时你必须重新学习所有内部细节(他们将在某些时候)
这些是关于如何在属性结果上调用release会引入问题的一些简单示例。许多现实世界的问题更加微妙,难以找到。