2021-01-14 OC中的property 和synthes
@property
有两个对应的词,一个是@synthesize
,一个是@dynamic
。
1、都不写
如果@synthesize
和@dynamic
都没写,那么默认的就是@syntheszie var = _var;
2、synthesize
@synthesize
的语义是如果你没有手动实现setter方法和getter方法,那么编译器会自动为你加上这两个方法。并且创建实例变量,这两个方法与这个实例变量是对应到的,创建的实例变量的名字与这个赋值的名字是相同的。
property在类中自动生成@syntheszie var = _var
;默认不写syntheszie
property就是依赖@synthesize
生成setter和getter方法的.
property是定义属性,也是依赖 @synthesize
创建变量的; 如果属性名字指定别的变量名,如果变量存在,则不会创建变量,否则创建对应名字的变量
分类中不会自动合成属性,匿名分类 ( 扩展)中可以自动合成属性
3、dynamic
@dynamic
告诉编译器,属性的setter与getter方法由用户自己实现,不自动生成。(当然对于readonly的属性只需提供getter即可)。假如一个属性被声明为@dynamic var
,然后你没有提供@setter
方法和@getter
方法,编译的时候没问题,
但是当程序运行到instance.var =someVar,由于缺setter方法会导致程序崩溃;
或者当运行到 someVar = var时,由于缺getter方法同样会导致崩溃。编译时没问题,运行时才执行相应的方法,这就是所谓的动态绑定。
若对于一个属性使用了@dynamic var = _var
,则编译器立马报错。这样你就无法像@synthesize
那样在var的setter方法和getter方法中使用_var,当然你更不能编写如下的setter方法和getter方法
@dynamic
最常用的使用是在NSManagedObject中,此时不需要显示编程setter和getter方法。原因是:@dynamic
告诉编译器不做处理,使编译通过,其getter和setter方法会在运行时动态创建,由Core Data框架为此类属性生成存取方法。
property在分类中xcode报警告,建议手写@dynamic var;
并且提供setter和getter方法
4,synthesize和dynamic
@synthesize,@dynamic
必须要提前声明, 否则编译报错,并且没有集成协议
类的interface中或者 类扩展的interface中 使用property, 才可以synthesize和dynamic, 报错如下
Property implementation must have its declaration in interface 'Synthesize' or one of its extensions
5, demo代码
@protocol SynthesizeProtocol
@property(nonatomic,strong)NSString *i;
@end
@interface Synthesize : NSObject<SynthesizeProtocol> {
@private
NSString*f;
}
@property (strong, nonatomic) NSString *a;
@property (strong, nonatomic) NSString *b;
@property (strong, nonatomic) NSString *c;
@property (strong, nonatomic) NSString *d;
@property (strong, nonatomic) NSString *e;
@property (strong, nonatomic) NSString *f;
-(void)func1;
@end
@implementation Synthesize{
NSString*_ccc;
//proxyerObj*_eeeObj;
}
@synthesize a; //setA,a, 创建实例变量a, 如果不指定名字, 变量名与属性名字相同
//@synthesize b=_b; //默认的 会自动创建。setB,b,对应到ivar为_b上,创建实例变量_b
@synthesize c=_ccc; //setC,c, setter/getter方法对应实例变量为_ccc上,不会再创建新的实例变量
@synthesize d=_dddd; //setD,d,创建实例变量_dddd
////不会创建实例变量, 也不会有setter,getter,需要自己实现。但是编译器提供setter,getter可访问。
@dynamic e;
@dynamic f; //会覆盖,不会自动@synthesize f=_f;所以不会创建实例变量_f,不会创建setF,f方法
-(void)func1 {
a=@"asdfa";
//Use of undeclared identifier '_a'
//_a=@"123412341";
_b=@"asdfasd";
//Use of undeclared identifier 'b'
//b=@"asdfasdafsdf";
//Use of undeclared identifier 'c'
//c=@"asdfasd";
//Use of undeclared identifier '_c'
//_c=@"asdfasdfas";
_ccc=@"asdfasdads";
_dddd=@"asdfasdfasdf";
[self setF:@"asdfa"];
NSLog(@"%@", [self f]);
self.i=@"123";
[self setI:@"123412"];
//Use of undeclared identifier '_i'
//_i=@"12431314";
// 会崩溃
//Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Synthesize setE:]: unrecognized selector sent to instance 0x6000002d8b10'
// [self setE:@"9999991"];
// NSLog(@"%@", [self e]);
}
-(void)setF:(NSString *)ftomp{
f=ftomp;
}
-(NSString *)f{
return f;
}
运行结果
对象 <Synthesize: 0x600001410f40>, 类对象 Synthesize
实例方法: [
"- (void)func1",
"- (void)setF:(id)arg0 ",
"- (id)f",
"- (void).cxx_destruct",
"- (void)setC:(id)arg0 ",
"- (id)c",
"- (void)setA:(id)arg0 ",
"- (void)setB:(id)arg0 ",
"- (id)a",
"- (id)b",
"- (void)setI:(id)arg0 ",
"- (id)i",
"- (void)setD:(id)arg0 ",
"- (id)d"
]
实例变量: [
"NSString* f",
"NSString* _ccc",
"NSString* a",
"NSString* _dddd",
"NSString* i",
"NSString* _b"
]
属性: [
"@property (nonatomic, strong) NSString* a",
"@property (nonatomic, strong) NSString* b",
"@property (nonatomic, strong) NSString* c",
"@property (nonatomic, strong) NSString* d",
"@property (nonatomic, strong) NSString* e",
"@property (nonatomic, strong) NSString* f",
"@property (nonatomic, strong) NSString* i"
]