引用计数
每个对象都有一个与之相关联多整数,被称作它的引用计数器或保留计算器,当某段代码需要访问一个对象时,该代码就将该对象的保留计数器值加1,表示我要访问该对象,当这段代码访问结束的时候,将对象的保留计数器数值减1,表示不再访问该对象了。当保留计数器的值为0时,表示不再有代码访问该对象了,此时它将被销毁同时占用的内存被回收。
对象的保留计数器值初始值为1。当一个对象即将要被销毁的时候,OC会向对象发送一条dealloc消息,这条消息可以在自己的对象中重写。
常见的几种调用方法:
-(id) retain;
-(oneway void) release;
-(NSUInteger) retainCount;
Eg:
#import <Foundation/Foundation.h>
@interface RetainTra : NSObject
@end
@implementation RetainTra
-(id) init
{
if (self = [super init]) {
NSLog(@"init : This is first call -- %d .",[self retainCount]);
}
return (self);
}
-(void) dealloc
{
NSLog(@"dealloc called . Bye Bye..");
[super dealloc];
}
@end
int main(int argc, const char * argv[]) {
RetainTra *tracker = [ RetainTra new]; //count:1 此处直接调用了init
[tracker retain];//count 2
NSLog(@"%d--1",[tracker retainCount]);
[tracker retain];//count 3
NSLog(@"%d--2",[tracker retainCount]);
[tracker release]; //count 2
NSLog(@"%d--3",[tracker retainCount]);
[tracker release]; //count 1
NSLog(@"%d--4",[tracker retainCount]);
[tracker release]; //count 0 调用了dealloc。。
//NSLog(@"%d--5",[tracker retainCount]);
return 0;
}
对象所有权
如果一个对象内有指向其他对象的实例变量,则称该对象拥有这些对象。如。car对象拥有其指向的engine和tire对象。同样,如果一个函数创建了一个对象,则称该函数拥有这个对象。
访问方法中的保留和释放
一个更好的解决对象释放问题的代码
-(void) setEngine :(Engine *) newEngine
{
[newEngine retain];
[engine release];
engine = newEngine;
}//setEngine
首先保留了新的engine对象,即使newEngine与engine是同一个对象,保留计数器的值也将先增加,然后立即减少。由于没有归0,engine对象意外的未被销毁,这样避免了错误发生。
在访问方法中,如果先保留新对象,然后再释放对象就不会出现问题了。
自动释放
不知道为什么,看到这个词的时候,前面一直紧张的内心忽然平静了下来。。。
今天在看引用计数和对象所有权上花了很多时间,加上老师讲了很多关于函数的基础概念,需要慢慢记忆的东西很多。