Objective-C中的@synthesize和@dynamic

来源:互联网 发布:交通违章查询软件下载 编辑:程序博客网 时间:2024/06/05 05:33

Apple的官方文档中, @synthesize主要有两个使用场景:

1.给属性对应的实例变量重命名. 看代码:

@interface Person : NSObject@property (nonatomic, copy) NSString *name;- (instancetype)initWithName:(NSString *)name;@end

定义了一个属性name, 编译器会默认生成一个与name对应的实例变量, 名称是在属性名前面加下划线, 即_name. 我们可以在类内部直接使用这个实例变量:

@implementation Person- (instancetype)initWithName:(NSString *)name {    if (self = [super init]) {        _name = [name copy]; // 在初始化方法中直接使用_name    }    return self;}@end

事实上, 上面的代码中还有一句隐含的代码, 在@implementation Person这一行下面, 有@synthesize name = _name; 这一句是编译器默认添加的, 作用就是把name属性对应的实例变量命名为 _name:

@implementation Person@synthesize name = _name; // 这一句为编译器默认添加, 不需要自己写出来- (instancetype)initWithName...@end

如果你不喜欢_name这个实例变量名, 或者有其他原因不能使用 _name这个名字, 你可以用@synthesize来给name属性对应的实例变量指定一个其它的名字, 比如:

@implementation Person@synthesize name = ivarName; // 指定实例变量的名字为ivarName- (instancetype)initWithName:(NSString *)name {    if (self = [super init]) {        ivarName = [name copy]; // 在初始化方法中使用指定的实例变量名    }    return self;}@end

此时, ivarName就和默认的_name作用一样了. 另外, 如果你只写了@synthesize name; 没有指定新的名字, 那么对应实例变量的名字就会和属性名一样, 都叫做name了:

@implementation Person@synthesize name; // 不指定新名字, 那么实例变量的名字也叫做name// 这里必须给方法的参数换个名字, 否则原来的参数名也叫name, 在方法内部会把实例变量name覆盖掉- (instancetype)initWithName:(NSString *)aName {    if (self = [super init]) {        name = [aName copy];    }    return self;}@end

2.如果你自己同时实现了一个属性的getter和setter, 或者一个只读属性的getter, 那么编译器就不会自动为我们生成属性对应的实例变量了. 此时, 我们可以使用@synthesize来手动创建该属性的实例变量:

@implementation Person@synthesize name = _name; // 同时实现getter和setter, 则需要手动创建属性对应的实例变量, 名字可以任意取- (instancetype)initWithName:(NSString *)name {    if (self = [super init]) {        _name = [name copy];    }    return self;}#pragma mark - getter & setter -- (NSString *)name {    return _name;}- (void)setName:(NSString *)name {    _name = [name copy];}@end

@dynamic的作用: 告诉编译器, 不要自动实现属性的getter和setter方法, 而要由我们手动去实现. 此时, 编译器也不会自动为我们生成属性对应的实例变量, 需要我们自己去处理. 而且要注意的是, 不能像上面的例子那样用@synthesize来手动创建该属性的实例变量, 因为实验表明, @dynamic和@synthesize是不能共存的. 那怎么办呢? 其实也简单, 我们可以在.m文件中增加一个实例变量, 让它来扮演属性对应的实例变量:

@implementation Person {    NSString *_name; // 增加一个实例变量, 跟name属性对应起来}@dynamic name; // 使用了@dynamic, 此时必须手动实现getter和setter- (instancetype)initWithName:(NSString *)name {    if (self = [super init]) {        _name = [name copy];    }    return self;}#pragma mark - getter & setter -- (NSString *)name {    return _name;}- (void)setName:(NSString *)name {    _name = [name copy];}@end

最后注意, 如果你使用了@dynamic, 却没有实现该属性的getter和setter, 那么在其它地方调用该属性的getter或setter时, 程序就会崩溃.

原创粉丝点击