您的位置:首页 > 运维架构

@property属性关键字的作用

2016-09-12 11:12 274 查看
属性关键字的作用

  现在我们iOS开发中,基本都是使用ARC(自动引用计数)技术,来编写我们的代码。因此在属性property中我们经常使用的关键字有strong,weak,assign,copy,nonatomic,atomic,readonly,readwrite,getter,setter。可能经常写代码的朋友,已经很清楚在什么情况下会使用他们。但可能并不清楚他们的含义,下面我先通过一张表总结下他们的作用:
属性关键字的作用
属性关键字
对属性的作用
strong
释放旧对象将旧对象的值赋予输入对象,再提高输入对象的索引计数为1,常使用在继承自NSObject的类。
weak
weak不增加对对象的引用计数,也不持有对象,因此不能决定对象的释放。它比assign多了一个功能,当对象消失后自动把指针变成nil
assign
简单赋值,不更改索引计数,适用于基础数据类型(NSInteger
CGFloat)和C数据类型(int float double char 等)简单数据类型。

copy
建立一个索引计数为1 的对象然后释放旧对象 对NSString它指出,在赋值时使用传入值的一份拷贝,拷贝工作由copy方法执行,此属性只对那些实行了NSCopying协议的对象类型有效。

atomic
和 nonatomic用来决定编译器生成的getter和setter是否为原子操作,atomic 设置成员变量的@property属性时 默认为是atomic 提供线程安全。在多线程环境下,原子操作是必要的否则会引起错误的结果。
nonatomic
非原子性访问对于属性赋值的时候不加锁,多线程并发访问会提高性能,如果不加此属性则默认是两个访问方法都为原子型事务访问。
readonly
此标记说明属性是只读的
readwrite
此标记说明属性会被当成读写的 这也是默认的属性
unsafe_unretained
跟weak类似,声明一个弱引用,但是当引用计数为0时,变量不会自动设置为nil
getter
指定 get 方法,并需要实现这个方法。必须返回与声明类型相同的变量,没有参数
setter
指定 set 方法,并需要实现这个方法。带一个与声明类型相同的参数,没有返回值(返回空值)

当声明为 readonly 的时候,不能指定 set 方法
用一个形象的例子说明assign,strong,copy的作用

NSString *houseOfMM = [[NSString alloc] initWithString:'MM的三室两厅'];

上面一段代码会执行以下两个动作:

1 在堆上分配一段内存用来存储@' MM的三室两厅 ' ,比如:内存地址为 0X1111 内容为 ' MM的三室两厅' ,

2 在栈上分配一段内存用来存储 houseForWife ,比如:地址为 0XAAAA 内容自然为 0X1111

然后我们分别看下(assign,strong,copy)使用场景:

1.assign的情况: NSString * myHouse = [ houseOfMM assign ];

此时 myHouse 和 houseOfMM 完全相同,地址都是 0XAAAA ,内容为 0X1111 ,即 myHouse 只是 houseOfMM 的别名,对任何一个操作就等于对另一个操作。因此 retainCount 不需要增加.(同进同出,关系好,一把钥匙,给我拿着)

2.retain的情况: NSString * myHouse = [ houseOfMM retain ];

此时 myHouse 的地址不再为 0XAAAA ,可能为 0XAABB ,但是内容依然为 0X1111 .因此 myHouse 和 houseOfMM都可以管理' 装梵几的三室两厅 '所在的内存。因此 retainCount 需要增加1.(有些独立,各自进出,两把钥匙)

3.copy的情况: NSString * myHouse = [ houseOfMM copy ];

此时会在堆上重新开辟一段内存存放@'MM的三室两厅',比如0X1122,内容为@'MM的三室两厅',同时会在栈上为myHouse分配空间,比如地址:0XAACC,内容为0X1122,因此retainCount增加1供myHouse来管理0X1122这段内存.(两套@'装梵几的三室两厅',条件好,分居了,房子一人一套,所以钥匙一人一把。)

关键字(assign,strong,copy)的使用场景

什么时候用assign,当然是破房子,简装的房子拉

基础类型(简单类型,原子类型):NSInteger,CGPoint,CGFloat,C数据类型(int,float,double,char等)

什么时候用copy

含有可深拷贝的mutable子类的类,如NSArray,NSSet,NSDictionary,NSData的,NSCharacterSet,NSIndexSet,NSString

(可深度拷贝的房子)

但是NSMutableArray这样的不可以,Mutable的不能用copy,不然初始化会有问题。切记

什么时候用strong

NSObject和其子类对象

weak:由ARC引入的对象变量的属性,比assign多了一个功能,对象消失后把指针置为nil,避免了野指针(不是null指针,是指向“垃圾”内存(不可用的内存)的指针)

用下面这张表来总结下关键字(assign,strong,copy)的使用场景

关键字(assign,strong,copy)的使用场景
assign
基本数据类型,如:NSInteger,CGPoint,CGFloat,C数据类型(int,float,double,char等)
copy
含有可深拷贝的NSCopy子类的类,如NSArray,NSSet,NSDictionary,NSData的,NSCharacterSet,NSIndexSet,NSString
strong/weak
NSObject和其子类对象 (Cocoa框架的类以及我们多数自定义的类)
属性关键字的对比

1.copy与strong

  1.copy 其实是建立了一个相同的对象 ,而strong不是 比如说 个NSString对象 地址是0x1111 内容为@"STR" ,copy到另外一个NSString之后 ,地址为0x2222 内容相同 新的对象retain 为 1 ,旧有对象没 有变化 ; retain到另外一个NSString之后,地址相同(建立了一个指针,指针拷贝)内容当然相同 这个对象的retain值+1 也就是说 retain 是指针拷贝 copy 是内容拷贝。

  2.strong的set方法是浅拷贝 copy的set方法是深拷贝

  3.copy的另外一个用法:

  copy是内容拷贝 对于像NSString的确是这样的 但是如果copy的对象是NSArray

  比如:NSArray*array = [NSArray arrayWithObjects:@"hello",@"world",@"baby"];

     NSArray*array2 = [array copy];

  这个时候 系统的确是为array2 开辟了一块新的内存空间 但是 array2中的每个元素 只是copy了指向array中相对应元素的指针 这便是所谓的浅复制。

2.assign和strong

  1.类似与C语言 当你malloc分配了一块内存 并且把它的地址赋给了指针a ,后来希望指针b也共享这一块内存 ,于是你又把a赋值给(assign)了b 。此时a和 b 指向同一块空间 ,当a不再需要这块内存的时候 ,能否直接释放它 答案是否定的 ,因为a并不知道b是否还在使用这块内存 ,如果a释放掉了这块内存 那么b在使用这块内存的时候 程序会crash掉

  2.1当中assign出现的问题如何解决 最简单的方法就是使用引用计数 (reference counting),还是上面的哪个例子 我们给内存设一个引用计数 当内存被分配并赋值给a 的时候 引用计数是1, 当把a赋值给b的时候 引用计数为2 这时如果a不再使用这块内存 ,它只需要把引用计数减1 表明自己不再用于这块内存 。b不再使用这块内存的时候也把引用计数减1 当引用计数为0 的时候 ,代表该内存不再被任何指针指向 系统可以直接把它释放掉。

  总结:上面两点就是assign和strong的区别 assign就是直接赋值 从而可能引起1.中的问题 当数据为int float等原生类型的时候,可以使用assign strong就如2.中所描述的问题一样 使用了引用计数 retain引起引用计数加1 release 引起引用计数减1 当引用计数为0的时候 dealloc函数被调用 内存被回收。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: