Objective-C中的@synthesize和@dynamic

本文详细介绍了Objective-C中的@synthesize和@dynamic的使用场景。@synthesize主要用于给属性的实例变量重命名,或者在自定义getter和setter时创建实例变量。而@dynamic则告诉编译器不自动生成getter和setter,需要程序员手动实现,且不能与@synthesize共存。未实现@dynamic声明的属性的存取方法会导致程序运行时崩溃。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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时, 程序就会崩溃.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值