前言
property修饰符和object所有权有一些关联。
1、属性中的修饰符的内存管理实现
assign(默认)(ARC、MRC都有)
用于CGFloat、NSInteger、基本数据类型(c类型)
用于不保留变量的对象、即相当创建弱引用而避免循环引用的发生
- (void)setter:(tupe *)xxxx //调用其setter方法时
{
_xxxx = xxxx; //直接赋值
}
strong(默认)(仅ARC有)
strong表示强引用关系,拥有对象的所有权(拥有对象的所有权即意味着要对其拥有的对象进行释放),引用计数器会加一
- (void) setter:(type *)XXXX //调用其setter方法时
{
[XXXX retain]; //新值引用计数加一保留
[_xxxx release]; //旧值引用计数减一释放
_xxxx = XXXX;
}
weak(仅ARC有)
weak表示弱引用关系,不拥有对象的所有权,目标对象销毁之后,属性会设置为nil
- (void) setter:(type *)XXXX
{
_xxxx = XXXX; /* 相当直接赋值,引用计数器不回加1 */
}
//当[XXXX release] , _xxxx == nil,即原来的指针变量指向的对象释放后,指针变量 = nil
copy(ARC、MRC都有)
copy引用计数加一,操作一个内存,注意在源对象可变(深拷贝)不可变(浅拷贝)时候的问题
- (void) setter:(type *)XXXX
{
[XXXX retain]; //新值引用计数加一保留
[_xxxx release]; //旧值引用计数减一释放
_xxxx = [XXXX copy]; //返回一个不可变的类型
}
retain(仅MRC有)
retain为当前对象指向的对象 引用计数+1保证不被释放
2、ARC的几个对象所有权关键字__strong 、__weak、__autoreleasing、__unsafe_unretained
- __strong(默认),只要有一个强指针指向对象,对象就不会释放
自己生成对象并持有
id __strong obj = [[NSObject alloc] init];
等价于
id obj = objc_msgSend(NSObject, @selector(alloc));
objc_msgSend(obj,@selector(init)); //
objc_release(obj);
自己不生成对象,但对象存在而持有
id __strong obj = [NSMutableArray array];
等价于
id obj = objc_msgSend(NSMutableArray, @selector(array));
objc_release(obj);
- __weak,不保持引用对象的存活,没有强引用指向它,那么弱引用置为nil
只能修饰对象类型,不能修饰基本类型
Number* __weak num = [[Number alloc] init];
__weak修饰的指针变量指向的对象被释放时,指针变量会被设置为nil
id __weak obj1 = obj;
在编译器中实际上等价于:
id obj1; //定义一个id类型的指针变量
obj1 = 0; //将指针变量置为nil
objc_storeWeak(&obj1, obj); //让指针变量obj1 指向 obj
objc_storeWeak(&obj1, 0); //让指针变量obj1 指向 nil
__weak实现原理
objc_storeWeak()函数会把第二个参数的对象的地址作为key,并将第一个参数(__weak关键字修饰的指针的地址)作为值,注册到weak表中。如果第二个参数为0(说明对应的对象被释放了),则将weak表中将整个key-value键值对删除
- __autoreleasing
使用__autoreleasing修饰的指针变量会会注册到autoreleasepool中,和在非ARC中[对象 autorelease]效果相同
Number* __autoreleasing num = [[Number alloc] init];
访问附有__weak修饰符的指针变量时,该变量会被自动注册到autoreleasepool中
id __weak obj1 = obj0;
NSLog("class=%@", [obj1 class]);
//等价于以下代码
id __weak obj1 = obj0;
id __autoreleasing tmp = obj1;
NSLog("class=%@", [tmp class]);
_objc_autoreleasePoolPrint()函数
该函数属于私有函数,可以打印出注册到调用函数处所属的autoreleasepool中的对象。
- __unsafe_unretained
__unsafe_unretained修饰符的变量也不能持有对象.
id __unsafe_unretained obj1 = obj;
//即obj1不能持有对象
__unsafe_unretained修饰符的变量指向的对象被废弃了那么该指针变量的值不会被置为nil,依然还是以前的值.但它已经是野指针了,可能会导致问题
3、属性修饰符合对应的所有权修饰符
所有权的意思是,谁所有谁负责释放。
属性修饰符 | 对应的所有权修饰符 | 作用 |
---|---|---|
strong (ARC) | __strong | 默认使用,对引用对象强引用 |
weak (ARC) | __weak | ARC才有的修饰符,对对象弱引用,对对象无持有权 |
copy (ARC、MRC) | __strong(赋值的是复制的对象) | 类似于strong,不过在赋值时进行copy而不是retain。一般用于保留某个不可变对象(如NSString),并防止它被意外改变 |
retain (MRC) | __strong | 基本等价于strong |
assign (ARC、MRC) | __unsafe_unretained | 默认使用,setter方法直接赋值,不进行retain操作,一般用于处理基本数据类型 |
__unsafe_unretained (ARC) | __unsafe_unretained | 不安全的修饰符,修饰的变量不属于编译器的内存管理对象,基本等价于assign |