@Property
本质:@property = ivar(带下划线的实列变量) + getter/setter(存取方法);
使用@property定义属性后,编译器会自动编写访问属性所需的方法,此过程叫做“自动合成”(autosynthesis)。
这个过程由编译器在 编译期执行,所以编辑器里看不到这些“合成方法”(synthesized method)的源代码。除了生成方法代码 getter、setter 之外,编译器还要自动向类中添加适当类型的实例变量,并且在属性名前面加下划线,以此作为实例变量的名字。
系统做的事:
1. 系统会在 ivar_list 中添加一个成员变量的描述
2. 在 method_list 中增加 setter 与 getter 方法的描述
3. 在属性列表中增加一个属性的描述
如果.m 文件中:@synthesize和@dynamic我们都没写,那么系统默认的就是@syntheszie var = _var,其实在.m文件中实际是存在@synthesize声明语句的,只是系统将其隐藏了。
比如:
使用@property声明一个属性name,系统默认的就是 @synthesize name = _name;
有时候会看到 @synthesize name这种写法 ,它等同于 @synthesize name = name;
如果在.h 文件中使用@property声明一个属性,在 .m 文件中同时又重写了setter和getter的话,就会报错,因为同时重写setter和getter方法,系统就不会自动帮我们生成成员变量。需要在.m 文件中给这个属性添加上@synthesize关键字:@synthesize name = _name;
什么时候不会使用自动合成?
同时重写了setter和getter时。
重写了只读属性的getter时。
使用了@dynamic时。
在@protocol中定义的所有属性。
在category中定义的所有属性。
重载的属性
@synthesize
@synthesize编译器期间,让编译器自动生成getter/setter方法。当有自定义的存或取方法时,就不会自动生成相应的方法,找不到实例变量编译器主动创建一个。
@synthesize obj = _obj 意义详解
意思是:为成员变量_obj起个属性名称叫obj。 这样写是为了区分成员变量_obj和属性名称obj,在.m里面使用的时候见到_objh就知道是成员变量了,见到self.obj就知道是属性了。操作self.obj 其实就是在操作 _obj
例如:
@implementation ViewController
@synthesize publicName = ffff;
如果类里没有ffff这个成员变量,它会自动帮你创建一个,并且帮你生成如下的setter和getter方法。
- (void)setPublicName:(NSString *)publicName{
ffff = publicName;
}
- (NSString *)publicName{
return ffff;
}
@synthesize,可以让属性 和 某个成员变量绑定。
可以让程序员指定实例(成员)变量,如果不指定实例变量,实例变量默认是属性名。 比如:@synthesize name ; 默认会生成一个同名的成员变量(name, 不带下划线的)作为set/get的目标。
@dynamic
@dynamic 告诉编译器:属性的 setter 与 getter 方法由用户自己实现,不自动生成。假如一个属性被声明为 @dynamic var,而且你没有提供 @setter方法和 @getter 方法,编译的时候没问题,但是当程序运行到 self.var = someVar,由于缺 setter 方法会导致程序崩溃;或者当运行到 someVar = var 时,由于缺 getter 方法同样会导致崩溃。
编译时没问题,运行时才执行相应的方法,这就是所谓的动态绑定。
注意:@dynamic 不能像 @synthesize 那样由系统在实现文件中(.m)自动生成实例变量,所以需要我们手动在.m类中 显式定义出实例变量 _var 。
@dynamic的作用是告诉编译器,此属性对应的set/get方法将会被动态提供。(使用方法时才会检查该方法是否存在,可以利用runtime 进行方法添加)
#import"People.h"
#import<objc/objc-runtime.h>
@interfacePeople() {
@public NSString *_name;
}
@end
@implementationPeople
@dynamic name;
+ (BOOL)resolveInstanceMethod:(SEL)sel {
if (sel == @selector(setName:)) {
class_addMethod([self class], sel, (IMP)setName, "v@:@");
return YES;
}else if (sel == @selector(name)){
class_addMethod([self class], sel, (IMP)getName, "@@:");
return YES;
}
return [super resolveInstanceMethod:sel];
}
void setName(id self, SEL _cmd, NSString* name){
if (((People*)self)->_name != name) {
((People *)self)->_name = [name copy];
}
}
NSString* getName(id self, SEL _cmd){
return ((People *)self)->_name;
}
@end
成员变量
1.成员变量的默认修饰是@protected。
2.成员变量不会自动生成set和get方法,需要自己手动实现。
3.成员变量不能用点语法调用,因为没有set和get方法,只能使用->调用。
属性
1.属性的默认修饰是@protected。
2.属性会自动生成set和get方法。
3.属性用点语法调用,点语法实际上调用的是set和get方法。
参考:
iOS 关键字 @property,@synthesize,@dynamic
iOS中@property、@synthesize和@dynamic的区别-搜云库 ⭐️⭐️⭐️⭐️⭐️