zoukankan      html  css  js  c++  java
  • @synthesize obj=_obj的意义详解 @property和@synthesize

    本文转载至 http://blog.csdn.net/ztp800201/article/details/9231969 

    http://hi.baidu.com/feng20068123/item/ca8952fa661e5342932af2c2

    写的非常不错,攒一个!!!!

    我们在进行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; 这才是最可靠的方法。

    坏的做法

    @interface Foo : NSObject {

            @private

    NSObject* myObj_;

    }

    @property(strong, nonatomic) NSObject* myObj;

    @end

    // …

    @implementation Foo

    @synthesize myObj = myObj_;

    • @end

    好的做法

    @interface Foo : NSObject

    @property(strong, nonatomic) NSObject* myObj;

    @end

    // …

    @implementation Foo

    @synthesize myObj = myObj_;

    @end

    You may still need to declare the underlying name of the variable if you need to access it directly, as when writing custom getters and setters:

    当你自己在为实例变量写setter和getter的时候,如果你在其中需要直接访问变量的话,你得声明名字带下划线的变量:

    错误的写法

    @interface Foo : NSObject

    @property(strong, nonatomic) NSObject* myObj;

    @end

    // …

    @implementation Foo

    @synthesize myObj;

    - (NSObject*)myObj

    {

            return self.myObj; // 会递归调用getter!

    }

    - (void)setMyObj:(NSObject*)myObj

    {

            self.myObj = myObj; // 会递归调用setter!

    }

    @end

    正确的写法

    @interface Foo : NSObject

    @property(strong, nonatomic) NSObject* myObj;

    @end

    // …

    @implementation Foo

    @synthesize myObj = myObj_;

    - (NSObject*)myObj

    {

            return myObj_; // 没问题.

    }

    - (void)setMyObj:(NSObject*)myObj

    {

            // 没问题

            myObj_ = myObj; // 进行赋值(ARC会处理必要的retain和release)

    }

    @end

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

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

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

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

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

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

    retain:会自动retain赋值对象

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

    http://blog.csdn.net/beautifularea/article/details/6886604

     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然后赋值;

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


    解释的非常好  ,学习了

  • 相关阅读:
    wpf如何将图片设置为窗体的背景
    C#用Oracle.DataAccess中连接Oracle要注意版本问题!
    C#格式化数值结果表
    将字符串的16进制转换成byte[]
    Java各个类型与byte[]的转换
    记录下 Jquery的使用
    页面div与顶部有缝隙问题
    Js 转换Json返回的时间格式(转)
    Div垂直居中水平居中
    C# 日期格式大全
  • 原文地址:https://www.cnblogs.com/Camier-myNiuer/p/4759164.html
Copyright © 2011-2022 走看看