iOS属性修饰符

当我们使用property来定义属性的时候,往往会为属性添加很多的修饰符,例如:nonatomic、assign、copy、strong、weak等等,本文将讨论这些属性修饰符的作用。

1、atomic
这个英文单词直译过来的话,是“原子的”的意思,那么在iOS中,“原子”代表着处理事件的一个完整操作,我们利用atomic这个关键字来定义属性,那么这个属性的setter和getter方法将具有“原子性“。更进一步来说,就如当项目中涉及到了多线程的时候,这个被nonatomic定义的属性同时被多个线程调用setter方法,这时候,就不会出现在一个线程还没有结束调用的setter方法时,另外一个线程就开始调用这个属性的setter方法。另外的线程一直要等到正在调用setter方法的这个线程调用结束后,才会调用setter方法。所以总的来说,atomic是应用帮助我们解决了多线程问题,但是正是由于这些操作是应用帮我们完成的。所以,程序的运行效率会受到很多的影响。
2、nonatomic
通过对atomic的了解,我们知道了”原子性“是什么意思,那么nonatomic正是atomic的反义词,翻译成中文是”非原子的“。如果用nonatomic来定义一个属性,应用就不会帮助我们去使这个被定义的属性具有多线程的安全操作。但是,目前绝大多数的定义仍然是nonatomic,原因就在于,nonatomic的效率比atomic高,虽然他不是线程安全的,但是我们可以手动去在合适的位子进行设计添加线程安全的代码,比如在单例模式中利用GCD或者是手动添加锁来保证线程安全。
3、修改setter和getter方法的名字
在property中如果不对setter和getter方法的名字做处理,那么setter方法就是setName(这里用name来代替变量名 ),getter就是name,但是有些时候我们希望使用自己想的setter方法和getter方法的名字,就需要在property中写上setter = operation1 , getter = operation2 (这里的operation1和2是自己给出的名字),那么现在的setter和getter方法也就相应地改变了。
4、readonly和readwrite
承接上面第三点,如果在property中改了名字,那么就要注意,如果写上了修饰符readonly,那么setter方法就不应该进行重新命名。因为readonly表示这个属性只能够进行读取,也就是只有getter方法,没有setter方法。相反,readwrite这个表示属性既可以被读取,又可以被修改。默认的情况下是readwrite,所以我们如果不希望定义的属性被修改,那么就要手动写上readonly修饰符。
5、copy和retain
说到copy,大家都会想到字符串或者是数组和字典,不难发现,这三种类型都是有可变类型的,所以,使用copy在内存管理上更加安全,下面就从原理上来了解下。
@property (nonatomic,retain) NSString *retainStr;
@property (nonatomic,copy)  NSString *copyStr;
- (void)test:
{
    NSMutableString *tempStr = [NSMutableStringstringWithFormat:@"123"];
    self.retainStr = tempStr;
    self.copyStr = tempStr;
    NSLog(@"tempStr:%p,%p", tempStr,&tempStr);
    NSLog(@"retainStr:%p,%p", _retainStr, &_retainStr);
    NSLog(@"copyStr:%p,%p",   _copyStr, &_copyStr);
}
这里分别用retain和copy定义了两个字符串,然后在创建了一个可变字符串对象,然后分别将可变字符串对象赋值给定义的两个字符串,接着每个对象打印了两个值,第一个是变量的地址,第二个是变量指向的对象的地址。
好了,现在可以进行分析:我们假设tempStr这个变量自身的地址为0x11,tempStr指向的对象也就是可变字符串对象123的地址为0x00,通过self.retainStr = tempStr;retainStr所指向的对象的地址也变成了0x00,而retainStr这个变量本身的地址为0x12,通过self.copyStr = tempStr;copyStr所指向的对象的地址变成了0x01,而不是0x00,所以他指向的不是原来的那个可变字符串,而是深拷贝出来一份对象,然后指向拷贝出来的对象的。copySte这个变量的地址为0x13。
通过上述的分析,我们从原理上了解了copy和retain的不同,接下来我们继续执行代码,看看在某些情况下不使用copy会有什么样的影响
[tempStr appendString:@"45"];
NSLog(@"retainStr:%@",  _retainStr);
NSLog(@"copyStr:%@",  _copyStr);
改变tempStr的值,从123变成了12345,接着打印出retainStr和copyStr的值,我们发现,retainStr的值为12345,copyStr的值为123,而我们所希望得到的值也应该是123,而不是12345。相信大家也都明白为什么会发生这样的现象,retainStr这个变量和tempStr这个变量都是指向于0x00这个对象的,那么改变了0x00这个对象的值,打印出来的结果也会随之改变。但copyStr这个变量指向的对象是由0x00深复制出来的一份对象,地址为0x01,所以,0x00的改变不会对0x01造成影响,所以打印结果也不会改变。
6、assign
默认情况下,就是用assign修饰属性的,assign修饰基本数据类型或者是指针的弱引用(例如delegate),他所修饰的属性只是进行简单的指针传递,不会引起引用计数的改变。
7、strong和weak
对于这两个修饰符来说,都是随着ARC的出现而出现的,我们在iOS中可以将它们称为强引用和弱引用,强引用就是类似于retain这样的引用,直接决定了所指对象的存亡,如果一个对象不被任何一个强引用去引用,那么这个对象就会从内存中释放掉。相反,弱引用不决定对象的存亡,也就是说,一个对象无论有多少个弱引用,没有强引用还是会被释放掉。如果要通俗来讲,那么strong相当于retain,weak相当于assign(但是多了一个功能,那就是当使用weak定义的属性所指向的对象被销毁之后,会自动将这个属性设置为nil)。我们在自定义协议的时候,非ARC模式下就使用assign,ARC模式下就使用weak。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值