属性关键字的作用

来源:互联网 发布:js跨域请求的问题 编辑:程序博客网 时间:2024/05/29 14:00

属性关键字的作用

现在我们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

含有可深拷贝的 mutable 子类的类,如 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函数被调用  内存被回收。

0 0