zoukankan      html  css  js  c++  java
  • Objectivec中的@property和@synthesize详解

    我们在进行iOS开发时,经常会在类的声明部分看见类似于@synthesize window=_window; 的语句,那么,这个window是什么,_ window又是什么,两个东西分别怎么用,这是一个比较基本的问题,也关乎我们理解Objective-C中对类、类的属性、类的存取器、类的局部变量的统一理解。
     
    在32位系统中,如果类的 @interface 部分没有进行 ivar 声明,但有 @property 声明,在类的 @implementation 部分有响应的 @synthesize,则会得到类似下面的编译错误:
    Synthesized property 'xX' must either be named the same as a compatible ivar or must explicitly name an ivar
    在 64-bit时,运行时系统会自动给类添加 ivar,添加的 ivar 以一个下划线"_"做前缀。

    上面声明部分的 @synthesize window=_window; 意思是说,window 属性为 _window 实例变量合成访问器方法。
    也就是说,window属性生成存取方法是setWindow,这个setWindow方法就是_window变量的存取方法,它操作的就是_window这个变量。通过这个看似是赋值的这样一个操作,我们可以在@synthesize 中定义与变量名不相同的getter和setter的命名,籍此来保护变量不会被不恰当的访问。
     
    写法一:
    @interface MyClass:NSObject{    
            MyObjecct *_myObject;  
    }  
    @property(nonamtic, retain) MyObjecct *myObject;  
    @end  
      
    @implementatin MyClass  
    @synthesize myObject=_myObject;  

    写法二:

    @interface MyClass:NSObject{  
            
    }  
    @property(nonamtic, retain) MyObjecct *myObject;  
    @end  
      
    @implementatin MyClass  
    @synthesize myObject=_myObject;  
    这个类中声明了一个变量_myObject,又声明了一个属性叫myObject,然后用@synthesize生成了属性myObject的存取方法,这个存取方法的名字应该是:setmyObject和getmyObject。
    @synthesize myObject=_myObject的含义就是属性myObject的存取方法是做用于_myObject这个变量的。这种用法在Apple的Sample Code中很常见。
    弄明白了这个语句的意思之后,我们也就清楚了myObject和_myObject的区别,那么,在使用的时候,有什么需要注意的地方,大家应该也都清楚了。是的,myObject是属性,而_ myObject才是变量,我们最终操作的变量都是myObject。
    那么,同样是存取操作,语句
    self.nameVarPtr = [[ObjectName alloc] init] 
    nameVarPtr = [[ObjectName alloc] init]  
    两种赋值方式的区别何在呢?

    self.nameVarPtr=xxx 这种赋值方式等价于调用 [self setnameVarPtr:xxx], 而setnameVarPtr:xxx的方法的实现又是依赖于@property的属性的,比如retain,assign等属性。

    nameVarPtr = xxx 的赋值方式,仅仅是对一个指针进行赋值。nameVarPtr仅仅是一个指针变量,记录了xxx的地址。在这个过程中不会调用setter方法,不会调用setter方法,就和@property没有关系,从而,也和retain,assign等属性没有关系。这种赋值方式就是一个简单的指针赋值。

    综上,对成员变量进行赋值,为防内存泄露需要注意的点:

    1.self调用setter方法的方式

    ObjectName*  tmp= [[ObjectName alloc] init];
    self.nameVarPtr =tmp;                 //retainCount=2
    [tmp release];                               //retainCount=1

    2.指针赋值方式,不会调用setter方法

    nameVarPtr= [[ObjectName alloc] init]; // retainCount=1

    所以,笔者建议大家在对某个变量进行赋值操作的时候,尽量要写self.myObj = xxx; 这才是最可靠的方法。

    @property和@synthesize可以自动生成某个类成员变量的存取方法

    readwrite:这个属性是默认的情况,会自动为你生成存取器

    assign:这个属性一般用来处理基础类型,比如int、float等等,如果你声明的属性是基础类型的话,assign是默认的,你可以不加这个属性

    natomic:默认是有该属性的,这个属性是为了保证程序在多线程情况,编译器会自动生成一些互斥加锁代码,避免该变量的读写不同步问题

    readonly:只生成getter不会有setter方法

    copy:这个会自动生成你赋值对象的克隆,相当于在内存中新生成了该对象的副本,这样一来,改变赋值对象就不会改变你声明的这个成员变量了

    retain:会自动retain赋值对象

    nonatomic:如果该对象无需考虑多线程的情况,请加入这个属性,这样会让编译器少生成一些互斥加锁代码,可以提高效率

     assign:指定setter方法用简单的赋值,这是默认操作。你可以对标量类型(如int)使用这个属性。你可以想象一个float,它不是一个对象,所以它不能retain、copy。

     assign:简单赋值,不更改索引计数(Reference Counting).使用assign: 对基础数据类型 (NSInteger)和C数据类型(int, float, double, char,等)

     retain:指定retain应该在后面的对象上调用,前一个值发送一条release消息。你可以想象一个NSString实例,它是一个对象,而且你可能想要retain它。

     retain:释放旧的对象,将旧对象的值赋予输入对象,再提高输入对象的索引计数为1 ,使用retain: 对其他NSObject和其子类 ,retain,是说明该属性在赋值的时候,先release之前的值,然后再赋新值给属性,引用再加1。

    copy:指定应该使用对象的副本(深度复制),前一个值发送一条release消息。基本上像retain,但是没有增加引用计数,是分配一块新的内存来放置它。copy是创建一个新对象,retain是创建一个指针,引用对象计数加1。copy:建立一个索引计数为1的对象,然后释放旧对象,copy是创建一个新对象,retain是创建一个指针,引用对象计数加1。

    readonly:将只生成getter方法而不生成setter方法(getter方法没有get前缀)。

    readwrite:默认属性,将生成不带额外参数的getter和setter方法(setter方法只有一个参数)。

    atomic:对于对象的默认属性,就是setter/getter生成的方法是一个原子操作。如果有多个线程同时调用setter的话,不会出现某一个线程执行setter全部语句之前,另一个线程开始执行setter的情况,相关于方法头尾加了锁一样。

    nonatomic:不保证setter/getter的原子性,多线程情况下数据可能会有问题。nonatomic,非原子性访问,不加同步,多线程并发访问会提高性能。先释放原先变量,再将新变量     retain然后赋值;

          注意,如果不加此属性,则默认是两个访问方法都为原子型事务访问。

  • 相关阅读:
    【已解决】github中git push origin master出错:error: failed to push some refs to
    好记心不如烂笔头,ssh登录 The authenticity of host 192.168.0.xxx can't be established. 的问题
    THINKPHP 5.0目录结构
    thinkphp5.0入口文件
    thinkphp5.0 生命周期
    thinkphp5.0 架构
    Django template
    Django queryset
    Django model
    Python unittest
  • 原文地址:https://www.cnblogs.com/mumue/p/2957441.html
Copyright © 2011-2022 走看看