文章目录
  1. 1. 1. 概念与区别:
  2. 2. 2. 历史和关系:
    1. 2.0.1. GCC
    2. 2.0.2. LLVM
  • 3. 问题:
  • 4. 参考:
  • 1. 概念与区别:

    • 成员变量:@interface的{}中包裹的变量

    @interface xx(){“成员变量”} -> { }包裹的是成员变量—基本数据类型(int/float)+实例变量(NSString)

    实例变量+基本数据类型变量=成员变量

    • 属性变量:声明标识符,对set/get方法声明,并不是变量

    属性并不是变量,是Objective-C 的一项特性,是属性的声明标识符,提供成员变量的访问方法的声明、控制成员变量的访问权限、控制多线程时成员变量的访问环境,主要的作用就在于封装对象中的数据,Objective-C 对象通常会把其所需要的数据保存为各种实例变量,实例变量一般通过“存取方法”(access method)来访问。@property 本质

    • 实例变量:成员变量的一种

    成员变量一种,不包含基本数据类型,@synthesize name = _name , _name实例变量。

    @interface MM (){
    int _age;//成员变量
    NSString * _name;//成员变量
    }
    @property (nonatomic,assign) int age;//属性,set/get方法声明,标识符 nonatomic:权限
    @end

    @implementation MM
    @synthesize age = _age;//生成实例变量_age,生成set/get方法,并将set/get方法作用于实例变量

    - (void)setAge:(int)age{//对_age的封装,便于子类和外部访问,同时设置访问权限等
    _age = age;
    }
    - (int)age{
    return _age;
    }
    @end

    2. 历史和关系:

    详情参考:IOS属性的作用

    GCC

    手动声明实例变量

    ***.h***
    @interface ViewController : UIViewController
    {
    //属性的实例变量
    NSString *myTitle;
    }
    //编译器遇到@property会自动声明对应的setter/getter
    @property (copy, nonatomic) NSString *myTitle;
    @end

    ***.m***
    //编译器遇到@synthesize会自动实现setter/getter方法
    //编译器遇到@synthesize回去访问myTitle的同名变量,如果没找到就报错。
    @synthesize myTitle;
    LLVM

    编译器就可以自动为属性生成一个名字带下划线的实例变量

    属性改变步骤:

    1. 第一版,最早版本
    ***.h***
    @interface ViewController : UIViewController
    {
    NSString *myTitle;
    }
    //编译器遇到@property会自动声明对应的setter/getter
    @property (copy, nonatomic) NSString *myTitle;
    @end

    ***.m***
    //编译器遇到@synthesize会自动实现setter/getter方法
    //编译器遇到@synthesize回去访问myTitle的同名变量,如果没找到就报错。
    @synthesize myTitle;

    2.第二版,不需要自己手动声明一个成员变量,关键字@synthesize会默认去访问myTitle的同名变量,如果找不到则会自动生成一个

    ***.h***
    @interface ViewController : UIViewController
    @property (copy, nonatomic) NSString *myTitle;
    @end

    ***.m***
    /*
    1.编译器遇到@synthesize会自动实现setter/getter方法;
    2.编译器遇到@synthesize回去访问myTitle的同名变量;
    3.如果找不到同名的变量,会自动生成一个私有同名变量myTitle
    4.因此现在开始就不用再手动声明一个实例变量了,
    */
    @synthesize myTitle;

    3.第三版,考虑到变量名和getter的方法名、setter的参数名一样,容易让人误会,引起警告,所以默认给属性生成的同名变量名带下划线。

    /*
    1.指定_myTitle作为myTitle的实例变量
    2.这样我们就可以去使用_myTitle,避免和setter名同名产生误会了
    */
    @synthesize myTitle = _myTitle;

    4.第四版,在IOS4.5后,也@synthesize可以省略了,最终就变成这样了

    @property (copy, nonatomic) NSString *myTitle;

    如果我们把上面的过程全部显示出来的话,本质如下:

    **.h**
    #import <UIKit/UIKit.h>

    @interface ViewController : UIViewController
    {
    /*
    ***被隐藏的代码:***
    1.这个默认是@synthesize myTitle = _myTitle;生成的
    2.所以如果我们手动设置@synthesize myTitle,那么我们编译器
    生成的变量就是NSString *myTitle,相当于@synthesize myTitle = myTitle,
    如果设置@synthesize myTitle = youTitle,那么编译器生成的变量就是NSString *youTitle了
    这要注意。
    */
    NSString *_myTitle;
    }
    @property (copy, nonatomic) NSString *myTitle;
    //***被隐藏的代码***
    //编译器遇到@property会自动声明setter/getter方法
    - (void)setMyTitle:(NSString *)myTitle;
    - (NSString *)myTitle;
    @end

    **.m**
    /*
    ***被隐藏的代码***
    1.@synthesize关键字会自动实现setter/getter的方法
    2.@synthesize myTitle = _myTitle指明了属性myTitle的实例变
    量是_myTitle,setter/getter操作的对象就是_myTitle.

    */
    @synthesize myTitle = _myTitle;
    - (void)viewDidLoad {
    [super viewDidLoad];
    _myTitle = @"123";

    }

    //***被隐藏的代码***
    //由关键字@synthesize自动实现
    - (NSString *)myTitle{
    return _myTitle;
    }
    - (void)setMyTitle:(NSString *)myTitle{
    _myTitle = myTitle;
    }

    代码说明:

    1. 编译器遇到关键字 @property ,自动声明setter/getter方法。
    2. 编译器遇到 @synthesize ,自动实现setter/getter方法。
    3. @synthesize myTitle = _myTitle; 为属性 myTitle 生成了一个实例变量 _myTitle ,所以我们对属性的操作self.myTitle 实质上都是在操作_myTitle 变量。

    所以属性、实例变量和成员变量的关系是:
    声明属性的时候编译器自动生成的实例变量,实例变量的本质就是成员变量,self.myTitle操作属性的时候实质上是在操作成员变量 _myTitle (也就是实例变量)。

    问题:

    1. 我们能否认为新编译器LLVM下的@property == 老编译器GCC的 成员变量+ @property + @synthesize 成员变量呢?

    答案是否定的,
    因为成员变量+ @property + @synthesize 成员变量的形式,编译器不会帮我们生成成员变量,因此不会操作成员变量了(注:区别就是LVVM操作实际是_成员变量,GCC操作成员变量,这样来说并不==);
    同时@synthesize 还有一个作用,可以指定与属性对应的实例变量,
    例如@synthesize myString = xxx;
    那么self.myString其实是操作的实例变量xxx,而非_String了。

    详情参考:成员变量和属性的前世今生

    1. 同时重写 setter/getter 的问题

    我们会发现,当我们同时重写 setter/getter 时会报错,为什么呢?这是因为当我们同时重写 setter/getter 时,编译器自动添加的代码@synthesize myTitle = _myTitle; 失效,就不会自动为我们生成实例变量_myTitle 了,setter/getter 操作的对象就不存在了。所以我们要加上@synthesize myTitle = _myTitle; ,手动指定setter/getter要操作的实例对象是_my

    参考:

    注:参考价值排序

    文章目录
    1. 1. 1. 概念与区别:
    2. 2. 2. 历史和关系:
      1. 2.0.1. GCC
      2. 2.0.2. LLVM
  • 3. 问题:
  • 4. 参考: