我最近一直在教自己Objective C,并注意到以下模式在教程和示例代码中使用了很多(包括来自Apple网站的样本)。
UIView *myUiView = [[UIView alloc] init];
self.uiView = myUiView;
[myUiView release];
我只是想知道,创建一个新变量似乎有点浪费,只是为了设置一个属性。我也看到过使用以下模式,但据我所知,在iOS设备上使用autorelease被认为是不好的形式,因为自动释放池占用了相当多的开销,这在移动设备上可能不太好
self.uiView = [[[UIView alloc] init] autorelease];
我最近一直在使用以下模式来设置属性,然后在属性上调用release(以减少属性本身的引用计数器)。
self.uiView = [[UIView alloc] init];
[self.uiView release];
我已经设法在一些没有不良影响的ViewControllers上使用它,但这是有效的代码,还是我错过了一些让它成为坏主意的东西?
答案 0 :(得分:1)
如果属性getter的实现只是返回对底层ivar的引用,那么它完全等效,你只需减少已分配对象的保留计数。
另一方面,如果你不能确定吸气剂是做什么的(如果它返回除了ivar以外的东西,例如一些计算结果等),那么它可能是危险的。
答案 1 :(得分:1)
属性getter是一个方法,它不必返回一个ivar,它实际上可以在任何地方获得它的返回值,所以你可以释放它,但它可能已经是一个自动释放的值。如果是这样的话,那你就麻烦了。
IOW,如果属性getter会做类似的事情(不常见,但可能有效):
- (NSString *) helloString
{
return [[myStringIVar copy] autorelease];
}
你做了:
[self.helloString release];
然后你以两种方式失败了:
IMO,最好直接发布ivar:
[myStringIVar release];
答案 2 :(得分:1)
它无效,即使在它工作的情况下它有点“丑陋”,另外两个只是修复属性的保留特性,使得在已经使保留计数为1之后保留计数2。
我倾向于做你在第一个例子或下面描述的内容。
在我的@interface
中@property (nonatomic, retain) UIView *uiView;
在我的@implementation
中@synthesize uiView = _uiView;
然后我设置了属性。
_uiView = [[UIView alloc] init];
答案 3 :(得分:1)
没有。它无效。
它可能适用于大多数保留属性,但不一定。它可能会破坏复制属性并分配属性。
属性只是一对方法,其中一个设置一个抽象实体,另一个设置它。 一般来说,绝对不能保证getter会为您提供刚刚传递给setter的完全相同的对象。例如,如果将可变字符串传递给NSString
复制属性,你绝对不会回到同一个对象。
使用前两种模式中的任何一种。第一个不浪费任何东西。局部变量很可能只存在于寄存器中。第二个的开销只会持续下一个自动释放池耗尽并且只有几个字节(请记住,实际对象在任何情况下都会持续self
。)
答案 4 :(得分:0)
根据引用计数器进行思考,使用属性值调用release
没有任何问题。但是,有些事情我个人不喜欢:
属性语法实际上只是方法调用的语法糖。那么,你的代码真正的样子是
[self setUiView: [[UIView alloc] init]];
[[self uiView] release];
这里的另一件事可能更多是由于我以奇怪的方式思考,但我喜欢将引用计数视为实际与引用有关。保存指向我的对象的指针的局部变量就是这样的引用。让它出现在代码中提醒我,我有一些事情要做,以便妥善清理(或者,如果没有,至少写一个简短的评论,为什么我不需要清理)。
直接通过该物业迫使我考虑引用计数,而我不喜欢。