Objective-C 语言中可以用 @property 标记快速创建属性,编译器会自动生成 setter
、getter
方法,这个过程就叫自动合成。
此过程由编译器在编译期执行。
自动合成失效的情况
- 同时重写
setter
、getter
- 重写了只读属性
getter
- 使用了 @dynamic 标记
- 在 protocol 中定义的所有属性
- 在 category 中定义的所有属性
- 重载父类的属性:当你在子类中重载了父类中的属性,必须使用 @synthesize 来手动合成 ivar
@property
本质
@property = ivar(实例变量) + getter/setter(存取方法);
复制代码
作用
编译器会自动生成 setter
、getter
方法,同时编译器会自动添加所写类型的的实例变量,并且在属性名前面默认添加下划线,作为实例变量的名字。
@property 对应的由两个词:@synthesize、@dynamic。
如果两个词都没有写,则默认为:
@synthesize var = _var;
@synthesize var;// 同上
复制代码
runtime 实现
我们每次增加一个属性,系统都会在 ivar_list 中添加一个成员变量的描述,在 method_list 中增加 setter
与 getter
方法的描述,在属性列表中增加一个属性的描述,然后计算该属性在对象中的偏移量,然后给出 setter
与 getter
方法对应的实现。
在 setter
方法中从偏移量的位置开始赋值,在 getter
方法中从偏移量开始取值。
为了能够读取正确字节数,系统对象偏移量的指针类型进行了类型强转。
@synthesize
作用
@synthesize 的作用就在于可以在编译器自动编写的时候指定这个自动添加的实例变量的名字。
例子
@interface
@interface testClass ()
@property (nonatomic, copy) NSString * aaa;
@end
复制代码
@implementation
@implementation testClass
// 指定aaa的实例变量为bbb
@synthesize aaa = bbb;
- (NSString *)aaa {
// 使用的实例变量为bbb
bbb = @"";
return bbb;
}
- (void)setAaa:(NSString *)aaa {
bbb = @"";
}
复制代码
@dynamic
作用
编译器不会自动生成setter
、getter
方法,由用户自己实现。
如果用户没有提供
setter
、getter
,编译的时候没有问题,但是当程序运行到setter
、getter
方法时,程序会自动崩溃。动态绑定
编译的时候没有问题,执行的时候才会找不到方法
解决崩溃方法
- 通过 runtime 机制在运行时添加属性的存取方法( runtime 的运用方法之一)
- 删掉 @dynamic
- 实现未提供的存取方法