前言
在 iOS 开发中,@property 几乎每天都在使用,但很多开发者对 getter 和 setter 的本质以及高级用法理解并不深入。
本文将从基础到进阶,系统讲解 getter 和 setter 的使用方式、底层原理以及常见面试问题。
一、什么是 Getter 和 Setter
Getter 和 Setter 是用于访问属性的两个方法。
- Getter:用于获取属性值
- Setter:用于设置属性值
1.基本示例
@property(nonatomic, strong) NSString *name;
编译器会自动生成:
- (NSString *)name;
- (void)setName:(NSString *)name;
2.调用方式
self.name = @"Tom";
NSString *n = self.name;
本质等价于:
[self setName:@"Tom"];
NSString *n = [self name];
二、Getter 和 Setter 的本质
@property 本质是语法糖,等价于:
@interface Person : NSObject {
NSString *_name;
}
- (NSString *)name;
- (void)setName:(NSString *)name;
@end
编译器会自动完成:
- 成员变量生成(如
_name) - getter 和 setter 方法实现
- 内存管理(ARC 环境下)
三、自定义Getter和Setter
1.自定义Getter
@property(nonatomic, assign, getter=isSingle) BOOL single;
生成:
- (BOOL)isSingle;
- (void)setSingle:(BOOL)single;
这样可以让代码更符合语义:
if (self.isSingle) {
}
2.自定义Setter
@property(nonatomic, assign, setter=setAgeValue:) int age;
生成:
- (int)age;
- (void)setAgeValue:(int)age;
3. 同时自定义 Getter 和 Setter
@property(nonatomic, assign, getter=isVIP, setter=setVIPStatus:) BOOL vip;
生成:
- (BOOL)isVIP;
- (void)setVIPStatus:(BOOL)vip;
四、手动实现 Getter 和 Setter
1.Getter(懒加载)
- (NSMutableArray *)dataArray {
if (!_dataArray) {
_dataArray = [NSMutableArray array];
}
return _dataArray;
}
2.Setter(数据处理)
- (void)setName:(NSString *)name {
_name = [name uppercaseString];
}
3.Setter正确写法
- (void)setName:(NSString *)name {
if (_name != name) {
_name = [name copy];
}
}
注意:
- 不要使用
self.name = name,否则会导致递归调用 - 应直接操作成员变量
_name
五、属性修饰符对Setter的影响
1.strong
@property(nonatomic, strong) NSObject *obj;
本质是强引用赋值。
2.copy
@property(nonatomic, copy) NSString *str;
本质:
_str = [str copy];
用于防止外部修改可变对象。
3.assign
@property(nonatomic, assign) int age;
直接赋值。
4. weak
@property(nonatomic, weak) id delegate;
不会增加引用计数,对象释放后自动置为 nil。
六、readonly 与 readwrite
1.readonly
@property(nonatomic, readonly) NSString *name;
只生成 getter 方法。
2.readwrite
默认属性,生成 getter 和 setter。
3. 私有 Setter 技巧
// .h
@property(nonatomic, strong, readonly) NSString *name;
// .m
@property(nonatomic, strong, readwrite) NSString *name;
对外只读,对内可写。
七、atomic 与 nonatomic
1. atomic
默认属性,保证线程安全,但性能较低。
2. nonatomic
@property(nonatomic, strong) NSString *name;
推荐使用,性能更高。