selector

OC get set 方法理解

2018-07-18  本文已影响0人  落叶随风_90e5

OC get set 方法理解 get set方法不能同时重写

最近在了解oc的属性,oc的属性组成是由成员变量+set/get方法组成,我们都知道用@property 声明的属性 Xcode 会帮我们生成get set 方法,有时我们根据实际需要会重写get 或者set 方法.都是可以的.但是我们get set 方法都重写,就会报错 

解决方法:21行添加@synthesize name =_name;声明 下划线属性

原因是: @property 已经帮我们重写了get set 方法 ,而现在我们又全部重写了get set 方法.导致Xcode 认为我们写的这 get set 方法的属性和@propery 声明的属性不是同一个属性了,所以会报错. 类似于 @property (nonatomic) NSString * name; 依然是Xcode 帮写get set 方法,但是 自己写的 get set 方法没有对应的属性声明.简而言之就是因为当你复写了get和set方法之后@property默认生成的@synthesize就不会起作用了,这也就意味着你的类不会自动生成出来实例变量了,你就必须要自己声明实例变量

如果非要重写get set 两个方法

上图中第14行代码 就是@synthesize 的作用 起到一个声明 下划线属性的作用 但是 getset 方法是我们自己实现的

如上图 

加一个第 14 行代码的声明. 表示我们自己声明一个属性,但是没事get set方法 需要自己重写  

这样一来第16行 代码可有可无.

若 没有第16行 就类似c++ 一样了.无法突出oc 特性

加了第16 行代码 就有真正OC语言的特性,一见到@property 就知道有get set 方法

当没有第16行代码,我们又重写了get 和set 方法,这个属性的get set 方法是我们自己实现

但是同时又有第16 行代码 ,Xcode 会处理发现 @property 和我们自己声明的东西是同一个属性,我们声明的get set 方法 会覆盖Xcode生成的get set 方法

这里面又涉及到两个属性@synthesize 和 @dynamic

iOS 6 之后 LLVM 编译器引入property autosynthesis,即属性自动合成。换句话说,就是编译器会为每个 @property 添加 @synthesize ,如以下形式: 

@synthesize propertyName = _propertyName; 

这行代码会创造一个带下划线前缀的实例变量名,同时使用这个属性生成getter 和 setter 方法。 

使用@synthesize 只有一个目的——给实例变量起个别名,或者说为同一个变量添加两个名字。 

如果要阻止自动合成,记得使用 @dynamic 。经典的使用场景是你知道已经在某处实现了getter/setter 方法,而编译器不知道的情况。 

此处我的理解是为了防止编译器使用自动合成生成新的setter/getter 会覆盖已经存在的旧的 setter/getter。 

自动合成没有任何内存的含义,所以它根本没有连接到ARC。 

如果你已经手动实现了 setter/getter方法,或着对 只读对象 实现了getter方法,那么自动合成不会产生任何影响。如果你在手动实现需要一个变量,只需声明它就可以了,不需要添加@synthesize来添加一个别名(尽管可以)。 

还有一种情形需要使用 @synthesize ,就是当在 protocol 代理 中声明并实现属性时。协议中声明的属性不会自动生成setter和getter,

总结 

1.@synthesize 的作用:是为属性添加一个实例变量名,或者说别名。同时会为该属性生成 setter/getter 方法。  

2.禁止@synthesize:如果某属性已经在某处实现了自己的 setter/getter ,可以使用 @dynamic 来阻止 @synthesize 自动生成新的 setter/getter 

3.内存管理:@synthesize 和 ARC 无关。  

4.使用:一般情况下无需对属性添加 @synthesize ,但一些特殊情形仍然需要,例如protocol中声明的属性。

这种情况下编译是没有错的,但是run 一下就会出错, 

@dynamic name; 

禁止生成 get set 方法了 

如果我们把上图的注释放开,run 一下也是正常的.

@property (nonatomic) NSString * name;

等同于

NSString * _name; 

-(void)setName:(NSString *)name { 

_name = name; 

-(NSString*)name { 

return _name; 

}

后者会覆盖前者的方法实现

上一篇下一篇

猜你喜欢

热点阅读