类的成员变量和属性

类的成员变量和属性

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

@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的问题。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容