在很久很久以前iOS是木有@property滴,我们必须自己定义实例变量和存取方法
@interface User : NSObject
{
NSString *name ;
NSInteger age;
}
@end
#import "User.h"
@interface User()
@end
@implementation User
-(void)setName:(NSString *)_name{
self->name = [_name copy];
}
-(NSString *)getName{
return self->name;
}
@end
属性@property给我们带来了什么?
@property = ivar + getter + setter; PS : 实例变量 = 成员变量 = ivar
@property 会根据(特质)的类型自定义合成不同的存取方法,这个过程由编译 器在编译期执行。
编译器还要自动向类中添加适当类型的实例变量,并且在属性名前面加下划线,以此作为实例变量的名字
属性可以拥有的特质分为四类:
原子性---nonatomic
读/写权限---readwrite(读写) readonly (只读)
内存管理语义---assign、strong、weak、unsafe_unretained、copy
方法名---getter=<name>、setter=<name>
@property (nonatomic, getter=isOn) BOOL on;
@synthesize
@synthesize 根据(特质)去添加存取方法 !
(如果没有指定@synthesize , 会为属性自动添加 @synthesize propertyName = _propertyName)
_propertyName就是实例变量的名称,propertyName是属性名称。
意味着使用属性可以通过存取方法去访问_propertyName实例变量。
直接访问实例变量不会调用属性的存取方法
@dynamic不会为属性自动创立合成方法,也不会自动添加属性。
#import <Foundation/Foundation.h>
@interface User : NSObject
@property (nonatomic,copy) NSString *subName;
@property (nonatomic,copy) NSString *name;
@end
#import "User.h"
@interface User()
@end
@implementation User
@synthesize subName = _subName;
@dynamic name ;
-(void)setName:(NSString *)name{
self.subName = [_subName stringByAppendingString:name];
}
@end
@dynamic 就是要告诉编译器,代码中用@dynamic修饰的属性,其getter和setter方法会在程序运行的时候或者用其他方式动态绑定,以便让编译器通过编译。其主要的作用就是用在NSManagerObject对象的属性声明上,由于此类对象的属性一般是从Core Data的属性中生成的,core data 框架会在程序运行的时候为此类属性生成getter和setter方法。
总结一下:
当你想手动管理 @property 的所有内容时,你就会尝试通过实现 @property 的所有“存取方法”(the accessor methods)或者使用 @dynamic 来达到这个目的,这时编译器就会认为你打算手动管理 @property,于是编译器就禁用了 autosynthesis(自动合成)。
因为有了 autosynthesis(自动合成),大部分开发者已经习惯不去手动定义ivar,而是依赖于 autosynthesis(自动合成),但是一旦你需要使用ivar,而 autosynthesis(自动合成)又失效了,如果不去手动定义ivar,那么你就得借助 @synthesize 来手动合成 ivar。
当你同时重写了 setter 和 getter 时,系统就不会生成 ivar(实例变量/成员变量)。这时候有两种选择:
手动创建 ivar 或者使用@synthesize ; 关联 @property 与 ivar。
PS : effective Objective-C建议我们在对象内部尽量直接访问实例变量而不是用存取方法。