atomic :
原子操作,默认属性,setter方法会变成下面的样子
{lock}
if (_a != a) {
[_a release];
_a = [a retain];
}
{unlock}
但是该关键字不能保证该变量的线程安全,只是对getter 和 setter方法进行了加锁操作,避免多个线程同时操作产生错误数据。
例如@property(acomic) NSMutableArray * values; 当values执行 addObject: ,removeObject的时候依然不是线程安全的。
acomic 只是保证提供一个完整的value 不保证线程安全,但是会比【nonatomic】更加消耗系统资源,使用的时候要斟酌
nonatomic
跟atomic相反,不加锁。
assign:
默认属性,用于基本数据类型(例如:CGFloat, NSInteger, BOOL)
weak:
弱引用,用于修饰对象,其值会在对象被释放后自动设置为nil。通常用于解决循环引用问题,例如delegate。
原理:
runtime维护了一个weak表,其实是一个hash表,key是所指对象的地址,value是weak指针的地址数组。
分为三步:
1、初始化时,runtime调用objc_initWeak函数初始化一个weak指针指向对象地址。
2、添加引用,objc_initWeak函数会调用objc_storeWeak函数,更新指针指向,创建对应的弱引用表
3、释放时,clearDeallocating函数根据对象地址获取weak指针数组并遍历置nil,然后从weak表移除,最后清理对象。
strong:
强引用,默认属性,修饰对象,对象被强引用时不会被释放
retain
- (void)setA:(id)a
{
if(_a != a){
[_a release];
_a = [a retain];
}
}
对新对象引用计数加1,并对旧对象release
copy
- (void)setA:(id)a
{
if(_a != a){
[_a release];
_a = [a copy];
}
}
表示重新建立一个引用计数为1的对象,并对旧对象release
readwrite
默认属性,表示可以读写,自动生成getter, setter方法
readonly
只读,只会生成getter方法
setter
指定生成setter方法的名字
getter
指定getter方法的名字
nonnull
表示对象可以是NULL / nil
nullable
表示对象不能为空
总结一下 默认属性有 atomic 、 assign、 readwrite
接下来补充一下 copy 和 mutable copy
首先来说系统的类
1> NSString、 NSArray等不可变对象 copy不会生成新对象,
mutableCopy会生成新对象并会变成可变对象,例如NSArray会变成NSMutableArray
2> NSMutableArray等可变对象, copy会产生新对象,并且是不可变对象 例如NSMutableArray 变成 NSArray
mutableCopy还是会产生新对象。
再说自定义的类 例如 Person 、Dog
自定义的类 实例化对象要想能拷贝 必须实现copyWithZone: 和 mutableCopyWithZone:
1 伪装实现
- (id)copyWithZone:(NSZone *)zone
{
return self;
}
这种实现方式没有开辟空间 、会使原对象引用+1
2.浅拷贝
- (id)copyWithZone:(NSZone *)zone
{
Person * newPerson = [[Person allocWithZone:zone] init];
newPerson.name = self.name;
return newPerson
}
这种实现方式会创建新的对象,但是新对象实例变量不会创建,比如newPerson.name 跟 oldPerson.name 指向同一处地址。
3.深拷贝
- (id)copyWithZone:(NSZone *)zone
{
Person * newPerson = [[Person allocWithZone:zone] init];
newPerson.name = [self.name mutableCopy];
return newPerson
}
这种实现会创建新的对象,并且对象实力变量也会创建新的
mutableCopyWithZone 跟 copyWithZone:一样,关键在于内部实现的方式,通常copyWithZone:实现浅拷贝,
mutableCopyWithZone实现深拷贝