OC MRC 成员变量, property, synthesize, dynamic

iOS @property、@synthesize和@dynamic

MRC 环境下: 创建一个 Person 类,  有 name, age, gender, weight 属性:

最早的写法: 成员变量

.h 文件
@interface Person : NSObject
//成员变量, 按苹果代码规范要带下划线, 以便和 setter, getter 方法的参数区分
{
    NSString *_name;
    NSString *_gender;
    NSInteger _age;
    CGFloat _weight;
}

//声明 setter, getter 方法
- (void)setName:(NSString *)name;
- (NSString *)name;

- (void)setGender:(NSString *)gender;
- (NSString *)gender;

- (void)setAge:(NSInteger)age;
- (NSInteger)age;

- (void)setWeight:(CGFloat)weight;
- (CGFloat)weight;

@end
.m 文件
@implementation Person

    //实现 setter, getter 方法
    - (void)setName:(NSString *)name {
        _name = name;
    }
    - (NSString *)name {
        return _name;
    }

    - (void)setGender:(NSString *)gender {
        _gender = gender;
    }
    - (NSString *)gender {
        return _gender;
    }

    - (void)setAge:(NSInteger)age {
        _age = age;
    }
    - (NSInteger)age {
        return _age;
    }

    - (void)setWeight:(CGFloat)weight {
        _weight = weight;
    }
    - (CGFloat)weight {
        return _weight;
    }

@end

Xcode 4.4 之前的写法: property 和 synthesize 共用

Xcode4.4版本之前: @property 和 @synthesize的功能是独立分工的

  • @property的作用是: 生成成员变量 set/get 方法的声明

      @property int age; 它的作用和下面两行代码的作用一致
      - (void)setAge:(int)age;
      - (int)age;
      //注意:属性名称不要加前缀_ 否则生成的get/set方法中也会有下划线
      //属性中带有下划线 _ 那么生成的get/set也会有下划线 _
      //@property int _age;
      //- (void)set_age:(int)_age;
      //- (int)_age;

  • @synthesize的作用

      //@synthesize age//实现 @property 声明的 set/get 方法, 生成私有的成员变量 age(不带下划线)

      生成带下划线的成员变量
      @synthesize age = _age//实现 @property 声明的 set/get 方法, 生成私有的成员变量 _age

      //如果在.h文件中没有定义 _age 成员变量的话,就会在.m文件中自动生成@private类型的成员变量_age

.h 文件
@interface Person : NSObject

@property (nonatomic, assign) NSString *name;//相当于拥有了以下两个方法的声明
//- (void)setName:(NSString *)name;
//- (NSString *)name;

@property NSString *gender;//相当于拥有了以下两个方法的声明
//- (void)setGender:(NSString *)gender;
//- (NSString *)gender;

@property NSInteger age;//相当于拥有了以下两个方法的声明
//- (void)setAge:(NSInteger)age;
//- (NSInteger)age;

@property CGFloat weight;//相当于拥有了以下两个方法的声明
//- (void)setWeight:(CGFloat)weight;
//- (CGFloat)weight;

@end
.m 文件
@implementation Person 

    @synthesize name = _name, gender = _gender, age = _age, weight = _weight;

    或分开写:
    @synthesize name = _name;//相当于以下两个方法
    //- (void)setName:(NSString *)name {
    //    _name = name;
    //}
    //- (NSString *)name {
    //    return _name;
    //}

    @synthesize gender = _gender;//相当于以下两个方法
    //- (void)setGender:(NSString *)gender {
    //    _gender = gender;
    //}
    //- (NSString *)gender {
    //    return _gender;
    //}

    @synthesize age = _age;//相当于以下两个方法
    //- (void)setAge:(NSInteger)age {
    //    _age = age;
    //}
    //- (NSInteger)age {
    //    return _age;
    //}

    @synthesize weight = _weight;//相当于以下两个方法
    //- (void)setWeight:(CGFloat)weight {
    //    _weight = weight;
    //}
    //- (CGFloat)weight {
    //    return _weight;
    //}

@end

 

Xcode4.4之后: @property 代替了 @synthesize的功能
 

     @property 的作用:

  1. 生成了成员变量 get/set 方法的声明
  2. 生成了私有的带下划线的的成员变量因此子类不可以直接访问,但是可以通过get/set方法访问。那么如果想让定义的成员变量让子类直接访问那么只能在.h文件中定义成员变量了,因为它默认是@protected
  3. 生成了get/set方法的实现 

     注意:

  1. 当让系统自动生成setter 以及 getter 方法实现时,此时系统会自动生成实例变量
  2. 如果我们自己重写了setter 和 getter 方法其中之一时,系统还会自动生成实例变量
  3. 如果我们自己重写了setter 和 getter ,那么此时系统不再自动生成实例变量,需要我们自己创建实例变量,或者使用@sythesize来生成实例变量, 此时的实例变量是私有的

//@sythesize 在.m文件中的作用:

    //(1)生成setter 和 getter 方法的实现
    //(2)生成内部操作的实例变量

.h 文件
@interface Person : NSObject

@property (nonatomic, retain) NSString *name;

@property (nonatomic, copy) NSString *gender;

@property (nonatomic, assign) NSInteger age;

@property (nonatomic, assign) CGFloat weight;

@end

注意: 当使用属性时, 为了防止内存泄露, 不同语义特性 retain, copy, assign 修饰的属性, 其 setter , getter 的内部实现有所不同

注意retain, copy 修饰的属性的 setter, getter 方法的实现

#pragma mark --- 不同语义特性下的setter 和getter 的内部实现
#if 0
//assign,系统默认
//setter 方法
- (void)setName:(NSString *)name {
    _name = name;
}

//getter 方法
- (NSString *)name {
    return _name;
}
#endif

#if 0
//retain
//setter 方法
- (void)setName:(NSString *)name {
     if (_name != name) {//避免重复操作
        [_name release];//解决内存泄露问题
        _name = [name retain];//解决野指针问题
    }
}
//getter 方法
- (NSString *)name {
    return [[_name retain] autorelease];//苹果推荐的getter方法的安全处理机制
}
#endif

#if 0
//copy
//setter 方法
- (void)setName:(NSString *)name {
    if (_name != name) {
        [_name release];
        _name = [name copy];
    }
}
//getter
- (NSString *)name {
    return [[_name retain] autorelease];
}
#endif

@dynamic

@dynamic 告诉编译器:属性的 setter 与 getter 方法由用户自己实现,不自动生成。假如一个属性被声明为 @dynamic var,而且你没有提供 @setter方法和 @getter 方法,编译的时候没问题,但是当程序运行到 instance.var = someVar,由于缺 setter 方法会导致程序崩溃;或者当运行到 someVar = var 时,由于缺 getter 方法同样会导致崩溃。编译时没问题,运行时才执行相应的方法,这就是所谓的动态绑定。

猜你喜欢

转载自blog.csdn.net/LeeCSDN77/article/details/82699015
今日推荐