初始化一个属性,点符号

在我的init方法中使用点符号来初始化retain属性为零是不是一个好主意?

有了这样的普通财产:

@property (nonatomic, retain) id foo; 

说我在init方法中设置self.foo = nil 。 合成的方法首先释放或自动释放foo (不完全确定潜在的障碍)。 在第一次接电话或接电话之前, foo保证是零吗? 或者它会指向随机垃圾,除非我明确地设置foo = nil没有点符号?

在我的init方法中使用点符号来初始化retain属性为零是不是一个好主意?

是的,这是一个坏主意。

1)对象已经在alloc + init序列中被清零了,所以不需要赋值为零。 换句话说,这个调用是没有用的,除非你的访问者有副作用(在这个阶段也应该避免访问者的副作用)。

2)你不应该用在部分构造的状态(例如initdealloc )中被覆盖的方法来给自己发送消息。

有没有第二个理由? 我经常做self.array = [NSMutableArray数组]; 在我的init方法。

原因是你的对象在部分构造的状态( init...deallocfinalize和许多copyWithZone:实现)中不应该对类接口的行为感兴趣。 你的class级应该有兴趣正确地进行初始化(如在init... ),并且在包括其成员(如dealloc )之后进行清理, 而不引入副作用。

考虑这个例子,你可以build立一个OS X的基础工具:

 #import <Foundation/Foundation.h> enum { UseItTheRightWay = true -OR- false }; @interface MONObjectA : NSObject { NSMutableArray * array; } @property (nonatomic, retain) NSArray * array; @end @implementation MONObjectA @synthesize array; - (id)init { self = [super init]; if (0 != self) { NSLog(@"%s, %@",__PRETTY_FUNCTION__, self); if (UseItTheRightWay) { array = [NSMutableArray new]; } else { self.array = [NSMutableArray array]; } } return self; } - (void)dealloc { NSLog(@"%s, %@",__PRETTY_FUNCTION__, self); if (UseItTheRightWay) { [array release], array = nil; } else { self.array = nil; } [super dealloc]; } @end @interface MONObjectB : MONObjectA { NSMutableSet * set; } @end @implementation MONObjectB - (id)init { self = [super init]; if (0 != self) { NSLog(@"%s, %@",__PRETTY_FUNCTION__, self); set = [NSMutableSet new]; } return self; } - (void)dealloc { NSLog(@"%s, %@",__PRETTY_FUNCTION__, self); [set release], set = nil; [super dealloc]; } - (void)setArray:(NSArray *)arg { NSLog(@"%s, %@",__PRETTY_FUNCTION__, self); NSMutableSet * tmp = arg ? [[NSMutableSet alloc] initWithArray:arg] : nil; [super setArray:arg]; [set release]; set = tmp; } @end int main (int argc, const char * argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; [[MONObjectB new] release]; /* the tool must be named 'Props' for this to work as expected, or you can just change 'Props' to the executable's name */ system("leaks Props"); [pool drain]; return 0; } 

在这个testing中切换行为的主要开关是UseItTheRightWay

如果UseItTheRightWay真的 ,我们得到的结果是:

 2011-05-09 01:52:11.175 Props[45138:a0f] -[MONObjectA init], <MONObjectB: 0x10010c750> 2011-05-09 01:52:11.177 Props[45138:a0f] -[MONObjectB init], <MONObjectB: 0x10010c750> 2011-05-09 01:52:11.179 Props[45138:a0f] -[MONObjectB dealloc], <MONObjectB: 0x10010c750> 2011-05-09 01:52:11.179 Props[45138:a0f] -[MONObjectA dealloc], <MONObjectB: 0x10010c750> leaks Report Version: 2.0 Process: Props [45138] < --- snip --- > Process 45138: 1581 nodes malloced for 296 KB Process 45138: 0 leaks for 0 total leaked bytes. 

如果UseItTheRightWay假的 ,我们得到的结果是:

 2011-05-09 01:55:51.611 Props[45206:a0f] -[MONObjectA init], <MONObjectB: 0x10010c750> 2011-05-09 01:55:51.614 Props[45206:a0f] -[MONObjectB setArray:], <MONObjectB: 0x10010c750> 2011-05-09 01:55:51.615 Props[45206:a0f] -[MONObjectB init], <MONObjectB: 0x10010c750> 2011-05-09 01:55:51.617 Props[45206:a0f] -[MONObjectB dealloc], <MONObjectB: 0x10010c750> 2011-05-09 01:55:51.618 Props[45206:a0f] -[MONObjectA dealloc], <MONObjectB: 0x10010c750> 2011-05-09 01:55:51.618 Props[45206:a0f] -[MONObjectB setArray:], <MONObjectB: 0x10010c750> leaks Report Version: 2.0 Process: Props [45206] < --- snip --- > Process 45206: 1585 nodes malloced for 297 KB Process 45206: 1 leak for 48 total leaked bytes. Leak: 0x100110970 size=48 zone: DefaultMallocZone_0x100005000 instance of 'NSCFSet', type ObjC, implemented in Foundation 0x70294ff8 0x00007fff 0x00001080 0x00000001 .O)p............ 0x00000001 0x00000000 0x00000000 0x00010000 ................ 0x707612a8 0x00007fff 0x00000000 0x00000000 ..vp............ 

问题#1

这个例子明显的失败是在dealloc引入的泄漏。

问题#2

第二件事会咬你的是微妙的:

 -[MONObjectA init] -[MONObjectB setArray:] -[MONObjectB init] 

这是什么??? -[MONObjectB setArray:] 之前调用-[MONObjectB init] ? 这意味着MONObjectB的实现 -[MONObjectB init]之前,甚至在-[MONObjectA init]退出之前使用。 那不好=

非平凡的devise只会产生一堆不良的副作用,怪异的行为,泄漏等等。 复杂的devise将会以非常明显的,非常微妙的方式失败,这很难追查到。 最好避免维护上的这种琐碎的差异,并从一开始就以适当的方式编写类(尽pipe你可以在相当长一段时间内完成这个工作,而没有明显的副作用)。