在对象之外访问实例变量时,总是应该通过属性来做,但在对象内部访问实例变量时那?除了几种特殊情况之外,建议在读取实例变量的时候采用直接访问,在设置实例变量的时候通过属性来做。
// 头文件
@interface EOCPerson : NSObject
@property (nonatomic, copy) NSString *firstName;
@property (nonatomic, copy) NSString *lastName;
- (NSString *)fullName;
- (void)setFullName:(NSString *)fullName;
@end
// 实现文件
// 使用点语法,通过存取方法来访问相关实例变量
- (NSString *)fullName
{
return [NSString stringWithFormat:@"%@ %@",self.firstName, self.lastName];
}
- (void)setFullName:(NSString *)fullName
{
NSArray *components = [fullName componentsSeparatedByString:@" "];
self.firstName = [components objectAtIndex:0];
self.lastName = [components objectAtIndex:1];
}
// 直接访问实例变量
- (NSString *)fullName
{
return [NSString stringWithFormat:@"%@ %@",_firstName, _lastName];
}
- (void)setFullName:(NSString *)fullName
{
NSArray *components = [fullName componentsSeparatedByString:@" "];
_firstName = [components objectAtIndex:0];
_lastName = [components objectAtIndex:1];
}
上面两种写法的区别:
1、直接访问实例变量不经过OC的“方法派发”,所以速度比较快。编译器所生成的代码会直接访问保存对象实例变量的那块内存。
2、直接访问实例变量时,不会调用其设置方法,这就绕过了为相关属性所定义的“内存管理语义”。
3、直接访问实例变量,不会触发“键值观测(KVO)”通知。
4、通过属性来访问有助于排查与之相关的错误,因为可以给获取方法、设置方法中新增“断点”,监控属性的调用者和访问时机。
特殊情况
1、在初始化方法中设置属性值,总是应该直接访问实例变量,因为子类可能“覆写”设置方法。但如果待初始化的实例变量声明在超类中,而我们无法在子类直接访问此实例变量的话,那就需要调用设置方法了。
2、“惰性初始化”,必须通过获取方法来访问属性,否则,实例变量就永远不会初始化。
- (EOCBrain *)brain
{
if (!_brain) {
_brain = [EOCBrain new];
}
return _brain;
}
网友评论