ARC 对象默认属性修饰符:@property (atomatic, readwrite, assign, strong) id object;
weak assign区别:
举个栗子��:
@property (nonatomic,strong)id strongObject;
@property (nonatomic,assign)id assignPoint;
@property (nonatomic,weak)id weakPoint;
***************************** ****************************** * ****************************** ******************************self.strongObject = [[NSObjectalloc]init];
self.assignPoint = self.strongObject;
self.weakPoint = self.strongObject;
// self.strongObject = nil;
NSLog(@"ASSIGNPOINT : %@ \nWEAKPOINT : %@",self.assignPoint,self.weakPoint);
Console print:ASSIGNPOINT : <NSObject: 0x7964b000>
WEAKPOINT : <NSObject: 0x7964b000>
而当注释 // self.strongObject = nil;被打开后, 可能就会崩溃.(可能不崩溃?因为_strongObject内存可能还没被真正释放,只是引用计数变为0了,可以嵌套一个循环多操作几次就会崩溃了)原因:首先,assign和weak不会对指向的内存做retain操作,所以当它们指向的内存引用计数为0时就会被释放。assign和weak的区别是,当指向的内存被释放后,weak指向的内存会自动置为nil,访问nil指针不会崩溃,而assign指向的内存不会自动置为nil(野指针),当访问野指针时就会导致崩溃。
copy strong 区别:
copy修饰的对象不会对引用的对象造成影响,strong修饰的对象修改会对引用的对象造成影响。
举个栗子...
@property (nonatomatic, strong) NSArray * array1;
@property (nonatomatic, copy) NSAarry *array2;
************************************************************************************************************************
NSMutableArray *array = [[NSArrayarrayWithObject:@"yyyycccczzzz"]mutableCopy];
self.array1 = array;
self.array2 = array;
[array addObject:@"so strong!"];
NSLog(@"\nARRAY1 CONTENT ----- %@\nARRAY2 CONTENT ----- %@",self.array1,self.array2);
Console print:
ARRAY1 CONTENT ----- (
yyyycccczzzz,
"so strong!"
)
ARRAY2 CONTENT ----- (
yyyycccczzzz
)
什么原因导致的这种结果?分析一下这两种修饰符修饰的对象的setter方法都做了什么:array1的setter方法:_array1 先执行一次release操作,然后array执行一次retain操作,最后一步操作_array1 = array 。
array2的setter方法: _array2 先执行一次release操作, 然后array执行一次copy操作, 最后一步操作_array1 = array 。
很显然_array1和array指向了同一个空间,所以array变化了,_array1也会跟着变化;_array2是copy修饰的,copy会开辟新的空间,_array2指向的就是array copy的新空间和array指向的不是同一块空间,所以array怎么变化都不会影响_array2;
修饰数组时选择copy还是strong?
修饰可变数组时用strong,修饰不可变数组时用copy。
再举个栗子...
@property (nonatomic,copy)NSMutableArray *array1;
************************************************************************************************************************
self.array1 = [NSMutableArrayarrayWithObject:@"ycz"];
[self.array1addObject:@"so strong!"];
run ——> crash!
Console print:
2016-08-25 16:19:26.168 MessageForwarding[59042:5124805] -[__NSArrayI addObject:]: unrecognized selector sent to instance 0x79e1e7e0
原因:copy会把可变数组变成不可变数组,不可变数组执行addObject:导致崩溃,所以可变数组要用strong来修饰。
@property (nonatomic,strong)NSMutableArray *array1;
@property (nonatomic,strong)NSArray *array2;
************************************************************************************************************************
self.array1 = [NSMutableArrayarrayWithObjects:@"ycz",nil];
self.array2 =self.array1;
NSLog(@"FIRST ARRAY2 CONTENT:%@\n",self.array2);
[self.array1addObject:@"so strong!"];
NSLog(@"SEC ARRAY2 CONTENT:%@\n",self.array2);
FIRST ARRAY2 CONTENT:(
ycz
)
SEC ARRAY2 CONTENT:(
ycz,
"so strong!"
)
会发现array1添加了新对象后 NSArray 类型的array2也发生了变化,而在我们工程中NSArray的动态变化是我们不想见到的...所以NSArray不能用strong修饰,要用copy来修饰。
PS:以前一直以为weak修饰的对象出了大括号后会被立即释放,在看了某个大神的一篇blog后发现之前的理解是错的。
按之前的理解断点处str已经被释放了,po出来应该是nil,结果是:
原因是weak修饰的对象是被加到自动释放池释放的,而自动释放池释放时机是依赖runloop的,当结束了当前runloop后自动释放池才会去释放里面的对象(上面的例子也说明viewDidLoad和ViewWillAppear是在同一个runloop里)。
若有错误请帮忙指出,谢谢。
未完待续.....