Objective-C学习笔记(一)
每调用一次retain增加的是本对象的retainCount,如果有其它对象通过复合的形式包含了这个对象(指针指向同一个地址),那么它们的retainCount是一样的,retain的时候全部都会+1。例如:
[phone1 setKey: key1];
[phone2 setKey: key1];
NSLog (@"phone1 key retain = %d", [[phone1 key] retainCount]); // count = 1
NSLog (@"phone2 key retain = %d", [[phone2 key] retainCount]); // count = 1
NSLog (@"key1 retain = %d", [key1 retainCount]); // count = 1
[key1 retain];
NSLog (@"phone1 key retain = %d", [[phone1 key] retainCount]); // count = 2
NSLog (@"phone2 key retain = %d", [[phone2 key] retainCount]); // count = 2
NSLog (@"key1 retain = %d", [key1 retainCount]); // count = 2
有些情况如:
[phone1 setKey: key1];
[phone1 setKey: key1]; // 要设置的新对象与旧对象是同一个对象
这种情况下要用以下的方法才不会出错:
- (void) setKey: (Key *) newKey
{
[newKey retain];
[key release];
key = newKey;
} // setKey:
顺序不能改变,要先retain新对象,再release旧对象。如果先release旧对象,因为retainCount从1减到0了,所以旧对象要dealloc,而新对象跟旧对象就是同一个对象的话,新对象也跟着dealloc了,程序就出错了。
在很多教科书中,我们都会看到很多类似以下的操作:
NSString *name1 = [[NSString alloc] initWithString: @"Steven Mok"];
NSString *phone1 = [[NSString alloc] initWithString: @"186xxxxx598"];
NameCard *steven = [[NameCard alloc] initWithName: name1 andPhone: phone1];
// we're done with the strings, so we must dealloc them
[name1 release];
[phone1 release];
[steven print]; //如果真的release了,在这里就会出错,因为name和phone对象被dealloc了
他们的意思大概都是:对对象赋完值了,可以把临时对象dealloc了。包括我现在在看的这本书也是这么说的,而且都已经出现了好几章了。
但是我想这样并不正确。
对对象赋值也就是使指针指向新的对象。这个时候我们需要保留这个新对象,如果把它释放了,就等于把我们内部的对象也释放了,因为它们指向同一个地址。(我的理解是:dealloc是基于指针的操作,把从指针所指的地址开始、长度为对象所占长度的内存块释放)所以,释放它们就错了。
补充:也有可能是我误解了作者的意思,或者我把这个“释放”理解错了。如果initWith:函数里面有retain的话,那么下面的release是不会有问题的,但是release后不会释放内存,因为还是1。我想作者所说的释放是指:保留用到的那一份,扣掉不再用到的那一份。
更形象点说,虽然它们都是同一块内存,但我把它的retainCount从2减到1了,至少可以告诉系统,现在只有一个地方在使用它。从这个角度来看,name1所占的那份确实是释放掉了。如果是这样理解的话,书上的内容就是正确的。
浙公网安备 33010602011771号