美文网首页iOS学习iOS Developer
类的成员变量和属性

类的成员变量和属性

作者: 傻子與白癡 | 来源:发表于2017-06-16 10:50 被阅读110次

    类的成员变量和属性

    在看老项目代码时,我们经常会看到这样的代码:

    @interface ViewController ()
    {
        
        NSString *_name;
        NSUInteger _age;
        
    }
    
    @property (nonatomic, copy) NSString *name;
    @property (nonatomic, assign) NSUInteger age;
    
    @end
    
    
    @implementation ViewController
    
    @synthesize name = _name;
    @synthesize age = _age;
    
    @end
    

    然而,我们现在写代码时发现并没有写的这么复杂

    @interface ViewController ()
    
    @property (nonatomic, copy) NSString *name;
    @property (nonatomic, assign) NSUInteger age;
    
    @end
    
    @implementation ViewController
    
    @end
    

    其实,发生这种状况的根本原因是苹果将默认编译器从GCC转换为了LLVM(low level virtual machine),才不再需要为属性声明实例变量了

    在没有更改之前,属性的正常写法需要三个步骤:

    成员变量 + @property + @synthesize 成员变量
    

    如果我们只写

    成员变量 + @property 
    
    @interface ViewController ()
    {
        
        NSString *myString;
        
    }
    @property (nonatomic, copy) NSString * myString;
    @end
    

    编译时会报警告

    Autosynthesized property '�myString' will use synthesized instance variable '_myString', not existing instance variable 'myString'
    

    但更换为LLVM之后,编译器会在编译过程中检查有没有相应的实例变量,发现没有相应的实例变量就会自动生成一个带下划线开头的实例变量。因此,现在我们不必再声明一个实例变量。(注意:是不必要,不是不可以)

    @synthesize 语句只能被用在implementation代码段中,@synthesize的作用就是让编译器为你自动生成setter与getter方法,@synthesize 还有一个作用,可以指定与属性对应的实例变量,例如@synthesize myButton = xxx;那么self.myButton其实是操作的实例变量xxx,而不是_myButton了。

    如果.m文件中写了@synthesize myButton;那么生成的实例变量就是myButton;如果没写@synthesize myButton;那么生成的实例变量就是_myButton。所以跟以前的用法还是有点细微的区别。

    成员变量

    • 作用范围
      @public:在任何地方都能直接访问对象的成员变量
      @private:只能在当前类的对象中直接访问,如果子类要访问需要调用父类的getter/setter方法
      @protected:可以在当前类及其子类对象中直接访问(默认)
      @package:在同一个包下就可以直接访问

    • 注意
      无论父类是在@interface还是@implementation声明的成员变量子类都能拥有;但是子类能不能直接通过变量名来访问父类中定义的成员变量,需要看父类中定义的成员变量是由什么修饰符来修饰的。

    • 默认
      在.h中成员变量的默认修饰符是@protected
      在.m中成员变量的默认修饰符是@private

        @interface Student : NSObject
        {
        @public    
            NSString *_name;   
        @protected    
            NSString *_sex;
        @private    
            NSString *_age;
        @package    
            NSInteger _score;
        }
        @end
        
        @implementation Student
        {
        @public
            NSString *_source;
        @private
            NSString *_mother;
        @protected
            NSString *_father;
        @package
            NSInteger _height;
        }
        @end
      

    创建一个MidStudent类继承Student,可以发现,在MidStudent可以访问_name_sex_score,不能访问_age和.m中的所有成员变量;在类外部,可以访问_name_score,其余的都不能访问。

    属性

    属性声明以关键词@property开头。@property 可以出现在类的 @interface 块中方法声明的任何地方。@property 还可以出现在protocol 或者 category声明中。

    @property声明的属性不仅仅默认给我们生成一个_类型的成员变量,同时也会生成setter/getter方法。

    那些事儿
    • 早期的Xcode不支持自动合成成员变量的存取方法。
    • 后来Xcode智能了一点,可以用@synthesize关键字自动合成成员变量的存取方法。
    • 现在 Xcode 会在我们声明属性时自动合成存取方法 , 连@synthesize都不用写了。
    Q:我们能否认为新编译器LLVM下的@property == 老编译器GCC的成员变量+ @property + @synthesize 成员变量呢?
    A:否定的。 因为成员变量+ @property + @synthesize 成员变量的形式,编译器不会帮我们生成_成员变量,因此不会操作_成员变量了;同时@synthesize还有一个作用,可以指定与属性对应的实例变量,例如@synthesize myString = xxx;那self.myString其实是操作的实例变量xxx,而非_String了。

    补充 -- 类别中的属性

    经常会在ios的代码中看到在类别中添加属性,比如在:UINavigationController.h文件中会对UIViewController类进行扩展。

    @interface UIViewController (UINavigationControllerItem)
    @property(nonatomic,readonly,retain) UINavigationItem *navigationItem;
    @property(nonatomic) BOOL hidesBottomBarWhenPushed;
    @property(nonatomic,readonly,retain) UINavigationController *navigationController;
    @end
    

    注意:在这种情况下,是不会自动生成实例变量的,并且不会自动生成setter/getter方法。编译器会报出警告:

    Property 'xxx' requires method 'xxx' to be defined - use @dynamic or provide a method implementation in this category 
    Property 'xxx' requires method 'setxxx:' to be defined - use @dynamic or provide a method implementation in this category
    

    原则上类别是只能增加方法,能增加属性的原因是通过runtime解决无setter/getter的问题。

    相关文章

      网友评论

        本文标题:类的成员变量和属性

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