美文网首页
OC——属性和实例变量(或成员变量)

OC——属性和实例变量(或成员变量)

作者: Etre | 来源:发表于2016-09-10 13:42 被阅读0次

    以前:

    在老版本的Objective-C语言中,我们需要同时声明属性和底层实例变量,那时,属性是Objective-C语言的一个新的机制,并且要求你必须声明与之对应的实例变量,例如:

    @interface MyViewController :UIViewController
    {    
          __strong UIButton *_myButton;   //实例变量
    }  
      
    @property (nonatomic, retain) UIButton *myButton;  //属性
      
    @end 
    
    

    后来,苹果将默认编译器从GCC转换为LLVM(low level virtual machine),从此不再需要为属性声明实例变量了。如果LLVM发现一个没有匹配实例变量的属性,它将自动创建一个以下划线开头的实例变量。

    现在:

    1. @synthesize的作用(1):让编译器为你自动生成setter与getter方法。

    如果使用了属性的话,那么编译器就会自动编写访问属性所需的方法,此过程叫做“自动合成”( auto synthesis)。需要强调的是,这个过程由编译器在编译期执行,所以编辑器里看不到这些“合成方法” 的源代码

    @interface CYLPerson : NSObject
    
    //@property = ivar + getter + setter; (ivar = 实例变量 = 成员变量)
    //会生成两个实例变量,其名称分别为 _firstName与_lastName
    @property NSString *firstName;
    @property NSString *lastName;
    
    @end
    

    2. @synthesize 的作用(2):可以指定与属性对应的实例变量。

    例如 @synthesize myButton = xxx;那么self.myButton其实是操作的实例变量xxx,而不是_myButton了。这样写了之后,那么编译器会自动生成myButton的实例变量,以及相应的getter和setter方法。注意:_myButton这个实例变量是不存在的,因为自动生成的实例变量为myButton而不是_myButton,所以现在@synthesize的作用就相当于指定实例变量;

    如果.m文件中写了@synthesize myButton,那么生成的实例变量就是myButton;如果没写@synthesize myButton;那么生成的实例变量就是_myButton。

    问题:

    1. 什么情况下不会autosynthesis(自动合成)?

    • 同时重写了setter和getter时
    • 重写了只读属性的getter时
    • 使用了@dynamic时
    • 在 @protocol 中定义的所有属性
    • 在 category 中定义的所有属性
    • 重载的属性

    - 当你在子类中重载了父类中的属性,你必须 使用@synthesize来手动合成ivar。
    除了后三条,对其他几个我们可以总结出一个规律:当你想手动管理@property的所有内容时,你就会尝试通过实现@property的所有“存取方法”(the accessor methods),或者使用@dynamic来达到这个目的,这时编译器就会认为你打算手动管理@property,于是编译器就禁用了autosynthesis(自动合成)。

    举例说明:

    1438585043866695.png

    当你同时重写了setter和getter时,系统就不会生成ivar(实例变量/成员变量)。
    这时候有两种选择:

    • 要么如第14行:手动创建ivar
    • 要么如第17行:使用@synthesize foo = _foo; ,关联@property与ivar。

    2. @synthesize和@dynamic分别有什么作用?

    1)@property有两个对应的词,一个是@synthesize,一个是@dynamic。如果@synthesize和@dynamic都没写,那么默认的就是@syntheszie var = _var;
    2)@synthesize的语义是如果你没有手动实现setter方法和getter方法,那么编译器会自动为你加上这两个方法。
    3)@dynamic告诉编译器:属性的setter与getter方法由用户自己实现,不自动生成。(当然对于readonly的属性只需提供getter即可)。

    假如一个属性被声明为@dynamic var,然后你没有提供@setter方法和@getter方法,编译的时候没问题,但是当程序运行到instance.var = someVar,
    由于缺setter方法会导致程序崩溃;或者当运行到 someVar = var时,由于缺getter方法同样会导致崩溃。编译时没问题,运行时才执行相应的方法,这就是所谓的动态绑定。

    相关文章

      网友评论

          本文标题:OC——属性和实例变量(或成员变量)

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