所有权修饰
idobj= [[NSObjectalloc]init];(默认)
id__strong obj= [[NSObjectalloc]init];
id和对象类型没有明确制定所有权修饰符时,默认为__strong
{ //ARC有效
//自己生成并持有对象
id __strong obj =[ [NSObjectalloc]init];
}
//变量obj超出其作用域,强引用失效,自动释放自己吃用的对象。对象的持有者不存在,因此废弃对象
附有__strong修饰符的变量obj在超出其变量作用域时,即在该变量被废弃时,会释放被其赋予的对象。
{//取得非自己生成并持有的对象
id __strong obj = [NSMutableArrayarray];
//变量obj为强引用,持有自己的对象
}
//因为变量obj超出其作用域,强引用失效,自动释放自己吃用的对象
id__strong obj0 = [[NSObjectalloc]init];//对象A
id__strong obj1 = [[NSObjectalloc]int];//对象B
id__strong obj2 = nil;
obj0= obj1;
/*obj0持有由obj1赋值的对象B的强引用,因为obj0被赋值,所以原先持有的对对象A的强引用失效,对象A的所有者不存在,因此废弃对象A;此时持有对象B的强引用的变量变为obj0和obj1*/
obj2= obj0;
/*obj2持有由obj0赋值的对象B的强引用,此时持有对象B的强引用的变量为obj0、obj1和obj2*/
obj1= nil;
/*因为nil被赋予了obj1,所有对对象B的强引用失效,此时持有对象B的强引用的变量为,obj0和obj2*/
obj0= nil;
obj2= nil;
//对象B的所有者不存在,因此废弃对象B
{
id __strong test = [[Test alloc]init];
//test 持有Test对象的强引用
[test setObject:[[NSObjectalloc]init]];
//Test对象的obj_成员,持有NSObject对象的强引用
}
/*因为test变量超出其作用域,强引用失效,所以自动释放Test对象;Test对象的所有者不存在,因此废弃该对象;
废弃该对象的同时,Test对象的obj_成员也被废弃,NSObject对象的强引用失效,自动释放NSObject对象;NSObject对象的所有者不存在,因此废弃该对象*/
{
id test0 = [[Test alloc]init];//对象A
id test1 = [[Test alloc]init];//对象B
[test0 setObject:test1];
//Test对象A的obj_成员持有Test对象B的强引用;此时,持有Test对象B的强引用变量为Test对象A的obj_和test1
[test1 setObject:test0];
//Test对象B达到obj_成员持有Test对象A的强引用;此时,持有Test对象A的强引用的变量为Test对象B的obj_和test0
}
/*因为test0变量超出其作用域,强引用失效,所以自动释放Test对象A;test1变量也超出其作用域,强引用失效,自动释放Test对象B;
此时持有Test对象A的强引用的变量为Test对象B的obj_
持有Test对象B的强引用变量为Test对象A的obj_
内存泄露*/
循环引用容易引起内存泄露——应当废弃的对象在超出其生存期后继续存在。
对象在不被任何持有的状态下应予以废弃,但是,循环引用使得对象不能被再次废弃。
__weak修饰符的变量(即弱引用)不持有对象,所以在超出其变量作用域时,对象即被释放
自身强引用
idtest = [[Test alloc]init];
[testsetObject:test];
{
//自己生成并持有对象
id __strong obj0 = [[NSObjectalloc]init];
//因为obj0变量为强引用,所以自己持有对象
id __weak obj1 = obj0;
//obj1变量持有生成对象的弱引用
}
/*因为obj0变量超出其作用域,强引用失效,自动释放自己持有的对象。因为对象的所有者不存在,所以废弃该对象
*/
__weak修饰符,在持有某对象的弱引用时,若该对象被废弃,则此弱引用强自动失效且处于nil被赋值状态(空弱引用)
id__weak obj1 = nil;
{
//自己生成并持有对象
id __strong = [[NSObjectalloc]init]; //因为obj0变量为强引用,所以自己持有对象
obj1 = obj0; //obj1持有对象的弱引用
NSLog(@“A: %@”, obj1);//输出obj1变量持有的弱引用的对象
}
/*因为obj0变量超出其作用域,强引用失效,自动释放自己持有的对象;因为对象无持有者,所以废弃该对象
废弃对象的同时,持有该对象的弱引用的obj1变量的弱引用失效,nil赋值给obj1*/
NSLog(@“B:%@”,obj1); //输出赋值给obj1变量中的nil
使用__weak修饰符可避免循环引用。通过检查附有__weak修饰符变量是否为nil,可以判断被赋值的对象是否已废弃
__weak修饰符只能用于iOS5以上及OS X Lion以上版本的应用程序。在iOS4以及OS X Snow Leopard的应用程序中可使用__unsafe_unretained修饰符代替
//ARC无效
NSAutoreleasePool* poo
=[[NSAutoreleasePoolalloc]init];
//ARC有效
@autoreleasepool{
id __autoreleaseingobj2;
obj2 = obj;
}
在ARC无效时,用于生成/持有的方法必须遵守以下命名规则,alloc、new、copy、mutableCopy上述名称开始的方法在返回对象时,必须返回给调用方所应当持有的对象。ARC有效时需要在添加一条
init 以init开始的方法,必须是实例方法,并且必须要返回对象
-(id)initWithObject:(id)obj;
-(void)dealloc{
/*
此处运行该对象被废弃时必须实现的代码
*/
free(buffer_);
[[NSNotificationCenterdefautlCenter]removeObserver:self];
}
//不能书写[superdealloc];
structData{
NSMutableArray* array;
};
error:ARCforbids Objective-C objsinstructsor unionsNSMutableArray* array;
要把对象型变量加入到结构体成员中,可强制转换为void*或者是附加__unsafe_unretained修饰符
structData{
NSMutableArray__unsafe_unretained* array;
};
__bridge_retained转换与retain类似,__bridge_transfer转化与release相似;再给idobj赋值时retain即相当于__strong修饰符的变量.
void* p = (__bridge_retainedvoid *) [[NSObjectalloc]init];
NSLog(@“class= %@”,[(__bridge id)p class]);
(void)(__bridge_transferid)p;
当ARC有效时属性声明的属性与所有权修饰符的对应关系
属性声明 | 所有权修饰符 |
assign | __unsafe_unretained修饰符 |
copy | _strong修饰符(但是赋值的是被复制的对象) |
retain | _strong修饰符 |
strong | __strong修饰符 |
unsafe_unretained | __unsafe_unretained修饰符 |
weak | __weak修饰符 |