哥当初钻牛角尖钻了一个通宵才理解出来的。
1 创建对像需要使用某个类,当对像实释放的时候会自动调用这个类的dealloc方法。所以每个类有自己的dealloc方法,当别的类创建的对象被释的时候,自动调用的dealloc方法是属于另一个类的,与本类的dealloc方法无关。
2 circle类里的方法调用point类,那么实际上circle类就是在使用对象(origin)。所以调用point类的时候,在方法里要给对象retain。
3 在circle类里的dealloc方法里要给circle对象所使用的point对象release,这样当circle被释放的时候会同时把point对象计数器-1。(因为circle死了,没使用point了)
4 会出现这样的情况:circle对象先使用point1对象,然后又用换成使用point2对象。而这时候circle对象还没被dealloc,也就是对象point1还没被计数器-1操作。所以在circle类的方法里要写多一句[_origin release],要不然point1就没被-1操作了。“_origin”是circle声明的一个对象;“origin”是setOrigin方法里的参数。
这时产生了一个疑问:每次circle类创建对象的时候都会对自己所创建的对象(_origin)release再retain?那第一次circle创建对象的时候,对象不会直接被dealloc掉吗?
答案:
当对象“circle”还没有被创建的时候,“_origin”的计数器本来为0,你给 “_origin”发送多少次release或者retain都视为无效;只有当“_origin”被赋值为“origin”的时候,才能给“_origin”进行计数器操作。
当对象“circle”还没有被创建的时候,对象“point” 已经被创建了,此时对象“point”的计数器本来为1,而 实验证明“origin”这时是指向“point”对象(第一个被创建的对象)的一个指针,所以你给 “origin”发送release会使point对象内存被释放。
我发现circle类是这样声明的:
@interface VSCircle : NSObject
{
VSPoint *_origin;
}
- (void)setOrigin:(VSPoint*)origin;
- (VSPoint*)origin;
结论就是:“_origin”被赋值为“origin”之前“_origin”与“origin”是不同的,此时只能对“_origin”release或retain,这样才不会有影响。
实验证明可以有四种写法:
A写法:
[_origin release]; //给对象声明发送消息
_origin = origin;
[_origin retain]; //给对象声明发送消息
B写法:
[_origin release]; //给对象声明发送消息
_origin = origin;
[origin retain]; //给对象声明发送消息
C写法:
[_origin release]; //给对象声明发送消息
[origin retain]; //给参数origin发送消息
_origin = origin;
D写法:
[origin retain]; //给参数origin发送消息
[_origin release]; //给对象声明发送消息
_origin = origin;
其它写法程序无法正常运行也无法停止。
5 在初始化方法里头:self.name = name与_name = name的区别:
self.name是调用方法,_name = name是直接赋值。实例变量如果是基本数据型的(assign)可以赋值;如果是对象(retain,copy...)的就要调用set方法。一般使用self.name的格式安全,除非实例变量是只读的。只读的实例变量不能用self.name方法来初始化,因为只读变量没有set方法的。