在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
描述
property属性
synthesize 合成访问器方法
如: 1、在头文件中: 1. @property int count; 等效于在头文件中声明2个方法:
1. - (int)count; 2. -(void)setCount:(int)newCount; 2、实现文件(.m)中
@synthesize count;
等效于在实现文件(.m)中实现2个方法。 )count 2. { 3. return count; 4. } 5. -(void)setCount:(int)newCount 6. { 7. count = newCount; 8. }
例如:@interface MyClass() @property (nonatomic, copy) NSString *age; @end @implementation MyClass @synthesize age = _age ; - (void)setAge:(NSString *)age { ….. } - (NSString *)age { .... } @end 以上等效的函数部分由编译器自动帮开发者填充完成,简化了编码输入工作量。
格式:
声明property的语法为:@property (参数1,参数2) 类型 名字;
其中参数主要分为三类:
各参数意义如下:
1.读写特性:readonly 、readwrite
在Objective-C中,拥有这样两个读写特性:readwrite和readonly,意思简单明了,就是可读可写以及只读。默认情况下,属性默认是可读可写的。 readwrite,声明此属性为读写属性,即可以访问设置方法(setter),也可以访问获取方法(getter),与readonly互斥。 readonly,声明此属性为只读属性,只能访问此属性对应的获取方法(getter),与readwrite互斥。 2.setter语意
setter语意特性主要是用来告诉Xcode,对于这个属性,应该如何去自动实现它的setter方法。这个特性主要是针对非ARC情况的。
在Objective-C中,拥有三个setter语意特性:assign、retain和copy,默认情况下属性特性是assign的。
assign:简单赋值特性,它不会对索引计数(Reference Counting)进行更改。默认类型,setter方法直接赋值,而不进行retain操作
-(void)setStr:(NSString*)value{ str=value; } retain:setter方法释放(release)旧的对象,然后将旧对象的值赋予输入对象,再将输入对象的索引计数增加1(retain)。
-(void)setStr:(NSString*)v{ if(v!=str){ [str release]; str=[v retain]; } } 声明在setter方法中,需要对设过来的值进行retain 加1操作。如:
1. -(void)setName:(NSString*)_name{ 2. //首先判断是否与旧对象一致,如果不一致进行赋值。 3. //因为如果是一个对象的话,进行if内的代码会造成一个极端的情况:当此name的retain为1时,使此次的set操作让实例name提前释放,而达不到赋值目的。 4. if ( name != _name){ 5. [name release]; 6. name = [_name retain]; 7. } 8. } copy:setter方法进行Copy操作,与retain一样,建立一个索引计数为1的对象,释放掉旧对象。
-(void)setStr:(NSString*)v{ if(v!=str){ [str release]; str=[v copy]; } } 参数中比较复杂的是retain和copy,具体分析如下:
getter 分析
1、
1. @property(nonatomic,retain)test* thetest; 2. @property(nonatomic ,copy)test* thetest; 等效代码:
1. -(void)thetest 2. { 3. return thetest; 4. } 2、
1. @property(retain)test* thetest; 2. @property(copy)test* thetest; 等效代码:
1. -(void)thetest 2. { 3. [thetest retain]; 4. return [thetest autorelease]; 5. } setter分析
1、
1. @property(nonatomic,retain)test* thetest; 2. @property(retain)test* thetest; 等效于:
1. -(void)setThetest:(test *)newThetest { 2. if (thetest!= newThetest) { 3. [thetestrelease]; 4. thetest= [newThetest retain]; 5. } 6. } 2、
1. @property(nonatomic,copy)test* thetest; 2. @property(copy)test* thetest; 等效于:
1. -(void)setThetest:(test *)newThetest { 2. if (thetest!= newThetest) { 3. [thetest release]; 4. thetest= [newThetest copy]; 5. } 6. }
retain
代码说明
如果只是@property NSString*str; 则通过@synthesize自动生成的setter代码为:
1. -(void)setStr:(NSString*)value{ 2. str=value; 3. } 如果是@property(retain)NSString*str; 则自动的setter内容为:
1. -(void)setStr:(NSString*)v{ 2. if(v!=str){ 3. [str release]; 4. str=[v retain]; 5. } 6. } 什么时候使用这些语意特性呢?
只要是值类型、简单类型的类型,比如说NSInteger、CGPoint、CGFloat,以及C数据类型int、float、double,bool等,都应该使用assign。
那么对于含有可深复制子类的对象,比如说NSArray、NSSet、NSDictionary、NSData、NSString等等,都应该使用copy特性。
注意:对于NSMutableArray之类的可变类型,不能够使用Copy特性,否则初始化会出现错误。
至于其他的NSObject对象,那么都应该使用retain来进行操作,这也是绝大多数所使用的情况。
3.所有者特性
我们先来看看与所有权有关系的属性,关键字间的对应关系。
属性值 关键字 所有权
strong __strong 有
weak __weak 无
unsafe_unretained __unsafe_unretained 无
copy __strong 有
assign __unsafe_unretained 无
retain __strong 有
strong
该属性值对应 __strong 关键字,即该属性所声明的变量将成为对象的持有者。
weak
该属性对应 __weak 关键字,与 __weak 定义的变量一致,该属性所声明的变量将没有对象的所有权,并且当对象被抛弃之后,对象将被自动赋值nil。
并且,delegate 和 Outlet 应该用 weak 属性来声明。同时 iOS 5 之前的版本是没有 __weak 关键字的,所以 weak 属性是不能使用的。这种情况我们使用 unsafe_unretained。
unsafe_unretained
等效于__unsafe_unretaind关键字声明的变量;像上面说明的,iOS 5之前的系统用该属性代替 weak 来使用。
对于ARC来说,上一节中所说的getter语意特性将被所有者特性所代替。
在Objective-C中,拥有两个所有者特性:strong和weak。默认情况下属性特性是strong的。
对于strong来说,它就相当于getter语意特性中的retain特性,即这个特性的属性将会成为对象的持有者。这个特性称之为强引用。
@property(strong) MyClass *myObject;
相当于@property(retain) MyClass *myObject;
对于weak来说,它声明的属性不会拥有这个对象的所有权,如果弱引用指向的对象被deallocated的话,弱引用的对象会被自动设置为nil。
@property(weak) MyOtherClass *delegate;
相当于@property(assign) MyOtherClass *delegate;
简单讲strong等同retain
weak比assign多了一个功能,当对象消失后自动把指针变成nil,好处不言而喻。
强引用与弱引用的广义区别:
强引用也就是我们通常所讲的引用,其存亡直接决定了所指对象的存亡。如果不存在指向一个对象的引用,并且此对象不再显示列表中,则此对象会被从内存中释放。
弱引用除了不决定对象的存亡外,其他与强引用相同。即使一个对象被持有无数个弱引用,只要没有强引用指向他,那麽其还是会被清除。
面对ARC机制中,最令人头疼的就是“循环强引用”的问题,所谓循环强引用,就是我们申请了两个保险柜,然后分别将另外一个保险柜的钥匙锁在了保险柜当中。这样就会造成什么现象呢?我们完全就无法归还钥匙了,这两个保险柜就无法再重新使用了。那么使用弱引用,就不会出现这个问题了。
weak常用于网络delegate属性
原子特性
原子特性,简要来说,是针对多线程而设置的。Objective-C拥有两种原子特性,分别是atomic和nonatomic。
相比之下,swift目前还不支持这些特性。如果我们要实现线程安全,似乎只能使用objc_sync_enter此类的方法,来保证属性的处理只有一个线程在进行。或者使用属性观察器来完成这些操作。
如果使用多线程,有时会出现两个线程互相等待对方导致锁死的情况(具体可以搜下线程方面的注意事项去了解)。在没有(nonatomic)的情况下,即默认(atomic),会防止这种线程互斥出现,但是会消耗一定的资源,而如果使用nonatomic,就不会有这种阻止死锁的功能,但是如果我们确定不使用多线程的话,那么使用这个特性可以极大地改善应用性能,所以如果不是多线程的程序,打上(nonatomic)即可。
有个评友说的,感觉挺到位的:nonatomic 和 atomic 之间的根本区别不是死不死锁或者能不能阻止死锁,而是产不产生竞争。如果用atomic,那么编译器生成的set方法会在整个set逻辑外层加互斥锁,保证set动作是原子的,如果用nonatomic,那么就不会加互斥锁,所以多线程下同时set会有数据混乱的风险,但是atomic版本因为有互斥锁,等锁和释放锁都会有开销,所以影响性能。总之,只要不是自己乱写set,get,是不会有死锁问题的,而是等锁开销。
总结
我们总共介绍了四种属性特性,分别是读写特性、setter语意特性、所有者特性和原子特性。ARC是不支持setter语意特性的,它使用所有者特性。
iOS开发的建议
所有属性都声明为nonatomic
尽量避免多线程抢夺同一块资源
尽量将加锁、资源抢夺的业务逻辑交给服务器端处理,减小移动客户端的压力
参考:
http://www.jianshu.com/p/bcf734db475c
http://justcoding.iteye.com/blog/1444548
|
请发表评论