@property与@synthesize

作者: 2c8c24bf4556 | 来源:发表于2015-07-13 12:07 被阅读20084次

property属性

    提供成员变量的访问方法的声明、控制成员变量的访问权限、控制多线程时成员变量的访问环境。
    property不但可以在interface,在协议protocol.和类别category中也可以使用。

synthesize 合成访问器方法

  实现property所声明的方法的定义。其实说直白就像是:property声明了一些成员变量的访问方法,synthesize则定义了由property声明的方法。
  
  他们之前的对应关系是:property 声明方法 ->头文件中申明getter和setter方法 synthesize定义方法 -> m文件中实现getter和setter方法。
  
  在Xcode4.5及以后的版本中,可以省略@synthesize,编译器会自动帮你加上get 和 set 方法的实现,并且默认会去访问_age这个成员变量,如果找不到_age这个成员变量,会自动生成一个叫做 _age的私有成员变量。在.m文件中同时实现getter和setter时候需要@synthesize age = _age.

1.读写特性:readonly 、readwrite

在Objective-C中,拥有这样两个读写特性:readwrite和readonly,意思简单明了,就是可读可写以及只读。默认情况下,属性默认是可读可写的。

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];
    }  
} 

  copy:setter方法进行Copy操作,与retain一样,建立一个索引计数为1的对象,释放掉旧对象。
-(void)setStr:(NSString*)v{  
    if(v!=str){  
        [str release];  
        str=[v copy];
    }  
} 

什么时候使用这些语意特性呢?

只要是值类型、简单类型的类型,比如说NSInteger、CGPoint、CGFloat,以及C数据类型int、float、double等,都应该使用assign。
那么对于含有可深复制子类的对象,比如说NSArray、NSSet、NSDictionary、NSData、NSString等等,都应该使用copy特性。

注意:对于NSMutableArray之类的可变类型,不能够使用Copy特性,否则初始化会出现错误。

至于其他的NSObject对象,那么都应该使用retain来进行操作,这也是绝大多数所使用的情况。

3.所有者特性

对于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。

我们知道,如果使用多线程的话,有时会出现两个线程互相等待而导致的死锁现象。使用atomic特性,Objective-C可以防止这种线程互斥的情况发生,但是会造成一定的资源消耗。这个特性是默认的。

而如果使用nonatomic,就不会有这种阻止死锁的功能,但是如果我们确定不使用多线程的话,那么使用这个特性可以极大地改善应用性能。

相比之下,swift目前还不支持这些特性。如果我们要实现线程安全,似乎只能使用objc_sync_enter此类的方法,来保证属性的处理只有一个线程在进行。或者使用属性观察器来完成这些操作。

总结

我们总共介绍了四种属性特性,分别是读写特性、setter语意特性、所有者特性和原子特性。ARC是不支持setter语意特性的,它使用所有者特性。

相关文章

网友评论

  • Zszen:synthesize 相当于可以重构setter和getter 我是这么理解的
  • RenJK:“原子特性” 一节说的有误吧.nonatomic 和 atomic 之间的根本区别不是死不死锁或者能不能阻止死锁,而是产不产生竞争。如果用atomic,那么编译器生成的set方法会在整个set逻辑外层加互斥锁,保证set动作是原子的,如果用nonatomic,那么就不会加互斥锁,所以多线程下同时set会有数据混乱的风险,但是atomic版本因为有互斥锁,等锁和释放锁都会有开销,所以影响性能。总之,只要不是自己乱写set,get,是不会有死锁问题的,而是等锁开销。
    _Nevermore:解释的很到位,我来补充两点吧,
    1.atomic在单核cpu中可以保证读写安全,在多核cpu中不管用的,一.因为可能会有多个响应在不同的线程对同一个变量调用setter方法.二.在单个响应的同时,可能有另一个周期性的任务,在另一个线程也调用了setter方法,在同一个时间点,不同的时间片,调用setter方法
    2.要保证setter方法安全的,须手动加锁,例如NSLock,NSRecurisiveLock,NSConditon等
    神一样的男人卫:解释的很到位呀!
    devzhaoyou:@RenJK 这个解释对✔️
  • 水_水:在synthesize合成访问器方法中,最后一句:“在.m文件中同时实现getter和setter时候需要@synthesize age = _age."自实现的时候可以使用该语句,也可以不用该语句,使用该语句则在访问属性对应的实例变量的时候可以直接用age,不适用该语句则访问属性对应的实例便令则使用_age,getter和setter方法的实现如果不自定义,则系统会自动帮你生成一个版本。我这样的说法对吗?
    pFruHMXB:@神一样的男人卫 其实我现在的做法时,假如同时setter 和 getter 这个时间是不会自动生成成员变量 _age了,所以这个时间 自己单独声明 一个 _age的成员属性就可以了
    神一样的男人卫:在.m文件中同时实现getter和setter时候需要@synthesize age = _age,请问一般在什么情况使用这句比较合适呢?
    ecfb918e5ccf:对的。你说的很对
  • 2c8c24bf4556:通过导入运行时头文件:#import <objc/runtime.h>
    实现property的setter和getter方法就可以在类别中使用属性了.引用FDTemplateLayoutCell的代码:
    - (BOOL)fd_isTemplateLayoutCell {
    return [objc_getAssociatedObject(self, _cmd) boolValue];
    }

    - (void)setFd_isTemplateLayoutCell:(BOOL)isTemplateLayoutCell {
    objc_setAssociatedObject(self, @selector(fd_isTemplateLayoutCell), @(isTemplateLayoutCell), OBJC_ASSOCIATION_RETAIN);
    }
    乱尘:蟹蟹,runtime这是个好东西
  • 乱尘:请问类别中怎么说能用属性呢?

本文标题:@property与@synthesize

本文链接:https://www.haomeiwen.com/subject/byuuqttx.html