oc基础

2021-01-14 OC中的property 和synthes

2021-01-14  本文已影响0人  我是小胡胡分胡

@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"
]

上一篇下一篇

猜你喜欢

热点阅读