#2 有原因吗?我经常做 self.array = [NSMutableArray array];在我的 init 方法中.原因是你的对象不应该在部分构造状态(init...、dealloc、finalize)期间对类接口的行为感兴趣code>,以及许多 copyWithZone: 实现).您的类应该对正确初始化(如在 init... 中)感兴趣并在其自身包括其成员之后进行清理(如在 dealloc 中)没有引入副作用.考虑这个示例,您可以将其构建为 OS X 的基础工具:#import 枚举 { UseItTheRightWay = true -OR- false };@interface MONObjectA : NSObject{NSMutableArray * 数组;}@property (nonatomic, retain) NSArray * array;@结尾@implementation MONObjectA@合成数组;- (id)init{self = [超级初始化];如果(0!=自我){NSLog(@"%s, %@",__PRETTY_FUNCTION__, self);如果(UseItTheRightWay){数组 = [NSMutableArray 新];}别的 {self.array = [NSMutableArray 数组];}}回归自我;}- (void)dealloc{NSLog(@"%s, %@",__PRETTY_FUNCTION__, self);如果(UseItTheRightWay){[数组释放],数组= nil;}别的 {self.array = nil;}[超级dealloc];}@结尾@接口 MONObjectB : MONObjectA{NSMutableSet * 设置;}@结尾@实现 MONObjectB- (id)init{self = [超级初始化];如果(0!=自我){NSLog(@"%s, %@",__PRETTY_FUNCTION__, self);set = [NSMutableSet new];}回归自我;}- (void)dealloc{NSLog(@"%s, %@",__PRETTY_FUNCTION__, self);[设置发布],设置= nil;[超级dealloc];}- (void)setArray:(NSArray *)arg{NSLog(@"%s, %@",__PRETTY_FUNCTION__, self);NSMutableSet * tmp = arg ?[[NSMutableSet alloc] initWithArray:arg] : nil;[超级 setArray:arg];[设置发布];设置 = tmp;}@结尾int main (int argc, const char * argv[]) {NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];[[MONObjectB 新] 发布];/* 该工具必须命名为Props"才能按预期工作,或者您可以将Props"更改为可执行文件的名称 */system("泄漏道具");[池排水];返回0;}在这个测试中切换行为的主要开关是UseItTheRightWay.如果 UseItTheRightWay 是 true,我们会得到结果:2011-05-09 01:52:11.175 Props[45138:a0f] -[MONObjectA init], 2011-05-09 01:52:11.177 道具 [45138:a0f] -[MONObjectB 初始化],<MONObjectB: 0x10010c750>2011-05-09 01:52:11.179 道具 [45138:a0f] -[MONObjectB dealloc], <MONObjectB: 0x10010c750>2011-05-09 01:52:11.179 道具 [45138:a0f] -[MONObjectA dealloc], <MONObjectB: 0x10010c750>泄漏报告版本:2.0工艺:道具 [45138]<--- 剪断 --- >进程 45138:为 296 KB 分配了 1581 个节点进程 45138:0 泄漏,泄漏的字节总数为 0.如果 UseItTheRightWay 是 false,我们会得到结果:2011-05-09 01:55:51.611 Props[45206:a0f] -[MONObjectA init], 2011-05-09 01:55:51.614 道具 [45206:a0f] -[MONObjectB setArray:], <MONObjectB: 0x10010c750>2011-05-09 01:55:51.615 道具 [45206:a0f] -[MONObjectB 初始化],<MONObjectB: 0x10010c750>2011-05-09 01:55:51.617 道具 [45206:a0f] -[MONObjectB dealloc], <MONObjectB: 0x10010c750>2011-05-09 01:55:51.618 道具 [45206:a0f] -[MONObjectA dealloc], <MONObjectB: 0x10010c750>2011-05-09 01:55:51.618 道具 [45206:a0f] -[MONObjectB setArray:], <MONObjectB: 0x10010c750>泄漏报告版本:2.0工艺:道具 [45206]<--- 剪断 --- >进程 45206:为 297 KB 分配了 1585 个节点过程 45206:1 次泄漏,总共 48 个泄漏字节.泄漏:0x100110970 大小=48 区域:NSCFSet"的 DefaultMallocZone_0x100005000 实例,类型 ObjC,在 Foundation 中实现0x70294ff8 0x00007fff 0x00001080 0x00000001 .O)p…………0x00000001 0x00000000 0x00000000 0x00010000 .....................0x707612a8 0x00007fff 0x00000000 0x00000000 ..vp .....................问题 #1这个例子的明显失败是在dealloc中引入的泄漏.问题 2第二个会咬你的东西更微妙:-[MONObjectA init]-[MONObjectB setArray:]-[MONObjectB 初始化]这是什么???-[MONObjectB setArray:] before -[MONObjectB init] 被调用了吗?这意味着MONObjectB的实现在之前-[MONObjectB init],甚至在-[MONObjectA init]之前使用代码> 已退出.那不好=非平凡的设计只会产生一堆不良的副作用、奇怪的行为、泄漏等等.复杂的设计会以非常明显和非常微妙的方式失败,这可能很难追踪.最好避免因为这些琐碎的书面差异而引起的维护麻烦,并从一开始就以正确的方式编写类(即使您可以避免这样做很长一段时间,没有明显的副作用).Is it a bad idea to use the dot notation to initialize retain properties to nil in my init methods?With any ordinary property like this:@property (nonatomic, retain) id foo;Say in my init method I set self.foo = nil. The synthesized method first releases or autoreleases foo (not exactly sure of the underlying impementation). Is foo guaranted to be nil before the first setter or getter call? Or would it point to random garbage unless I explicitly set foo = nil without the dot notation? 解决方案 Yes, it is a bad idea.1) The object has already been zeroed in the alloc+init sequence, so it is not necessary to assign it nil. In other words, this call is useless unless you have side effects in your accessors (side effects in accessors should also be avoided at this stage).2) You should not message self with methods which are overridden while in partially constructed states (e.g. init and dealloc).The reason is that your object should not be interested in the class interface's behavior during partially constructed states (init..., dealloc, finalize, and many copyWithZone: implementations). your class should be interested in initializing properly (as in init...) and cleaning up after itself including its members (as in dealloc) without introducing side-effects.consider this example, which you can build as a Foundation tool for 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;}@endint 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;}The main switch to toggle behavior in this test is UseItTheRightWay.If UseItTheRightWay is true, we are given the result: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.0Process: Props [45138]< --- snip --- >Process 45138: 1581 nodes malloced for 296 KBProcess 45138: 0 leaks for 0 total leaked bytes.And if UseItTheRightWay is false, we are given the result: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.0Process: Props [45206] < --- snip --- >Process 45206: 1585 nodes malloced for 297 KBProcess 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............Problem #1This example's obvious failure is the leak, introduced in dealloc.Problem #2The second thing that will bite you is subtler:-[MONObjectA init]-[MONObjectB setArray:]-[MONObjectB init]What's this??? -[MONObjectB setArray:] is called before -[MONObjectB init]? That means that MONObjectB's implementation is used before -[MONObjectB init], and even before -[MONObjectA init] has exited. That's no good =Nontrivial designs will just produce a bunch of undesirable side effects, weird behavior, leaks, and so on. Complex designs will fail in very obvious, and very subtle ways which can be very difficult to track down. it's best to avoid maintenance headaches over such trivial written differences, and to write classes the proper way from the start (even though you could get away doing this for quite some time, without obvious side effects). 这篇关于初始化属性,点符号的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云! 07-13 02:20