@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