应该怎么用
首先看一下这几个属性关键字和作用
1. strong(ARC)=retain(MRC) // default 用于修饰基于NSObject的对象
2. weak // 弱引用,防止循环引用 用于修饰基于NSObject的对象
3. assign // default 使用来修饰标量类型的属性(在C语言中,枚举类型、字符型和各种整数的表示形式统一叫做标量类型)
用代码测试下
@interface TestAssign : NSObject
@property (nonatomic, [strong, weak, assign]) NSString *str; // [strong, weak, assign]代表选择strong或weak或assign
@end
@implementation TestAssign
- (instancetype)init
{
self = [super init];
if (self) {
NSString *tmpStr = [[NSString alloc] initWithFormat:@"张。。"]; // tmpStr引用计数为1
self.str = tmpStr; // 使用strong: tmpStr引用计数为2(+1); 使用weak: tmpStr引用计数1; 使用assign: tmpStr引用计数1
} // 超出tmpStr的作用域了,引用计数-1
return self;
}
@end
TestAssign *ta = [[TestAssign alloc] init];
if (ta.str != nil) {
NSLog(@"length: %lu", [ta.str length]);
} else {
NSLog(@"ta.str is nil");
} // 使用strong: "length: 3"; 使用weak: "ta.str is nil"; 使用assign: crash(EXC_BAD_ACCESS)
strong
strong的作用是对保持对象的引用,将其引用计数+1,根据上面代码TestAssign的init中在超出作用域后,tmpStr的引用计数为1(-1),这个是正是我们想要的。所以我们可以正确打印length
weak
weak并不会将对象的引用计数+1,所以在超出作用域后tmpStr的引用计数为0(-1),系统将回收此区域内存,但是weak在对象释放后会将str置为nil
assign
我们都知道assign使用来修饰标量类型的属性(在C语言中,枚举类型、字符型和各种整数的表示形式统一叫做标量类型)。它不会使对象的引用计数+1,考虑为什么NSObject的类型才可以用strong呢,是因为非NSObject的类型没有实现retain和release的方法,引用计数是基于运行时的。针对于上面的代码,在超出作用域后,tmpStr的引用计数为0,但是与weak不同的是assgin不会将str置为nil,所以向已经被回收的对象发送消息行为是不确定的,所以导致了crash(EXC_BAD_ACCESS)