1: 在 对象内部 尽量 直接访问 实例变量

在对象之外访问实例变量时, 总是应该通过属性来访问, 然而在对象内部, 在读取实例变量的时候尽量采用 直接访问的形式, 而在设置实例变量的时候通过属性来做, 例子如下:

@interface EOCPerson : NSObject

@property (nonatomic, copy) NSString * firstName;

@prpperty (nonatomic, copy) NSString* lastName;

- (NSString*)fullName;

- (void)setFullName:(NSString*)fullName;

@end

fullName 和 setFullName 可以这样来实现

- (NSString*)fullName{

return [NSString stringWithFormat:@""%@ %@",self.firstName,self.lastName];

}

- (void)setFullName:(NSString *)fulleName{

NSArray * components = [fullName componentsSeparatedByString:@" "];

self.firstName = [components objectAtIndex:0];

self.lastname = [components objectAtIndex:1];

}

在上述 fullName 的获取方法 和 设置方法, 我们使用 '点语法', 通过存取方法来访问实例变量, 假设重写 这两个方法, 不经由存取方法, 而是直接访问实例变量.

- (NSString*)fullName{

return [NSString stringWithFormat:@""%@ %@",  _firstName,  _lastName];

}

- (void)setFullName:(NSString *)fulleName{

NSArray * components = [fullName componentsSeparatedByString:@" "];

_firstName = [components objectAtIndex:0];

_lastname = [components objectAtIndex:1];

}

// 这两种方法有几个区别

由于不经过 OC 的 '方法派发' , 步骤, 所以直接访问实例变量的速度是当然比较快的, 在这种情况下, 编译器所产生的代码会直接访问保存实例变量的那块内存

直接访问实例变量, 不会调用其 '设置方法', 这就绕过了为相关属性所定义的 '内存管理语义' (nontamic, strong , copy 等),

如果直接访问实例变量, 那么不会触发 '键值观察' (KVO) 通知,这样是否会产生问题, 取决于具体的对象行为

通过属性来访问有助于排查与之相关的错误, 因为可以给 getter 和 setter 方法新增 断点, 监控该属性的调用集齐访问时机

// 有一个折中的处理方案, 在写入实例变量的时候, 通过其 '设置方法' 来做, 而在读取实例变量的时候, 则直接访问,

此方法既能提高读取操作的速度, 又能控制对属性的写入 操作, 之所以要通过 '设置方法' 来写入实例变量, 其首要原因在于. 这样做能够确保相关属性的 '内存管理语义' 得意贯彻

但是,选用这种,需要注意几个问题

(1), 在初始化方法中应该如何设置属性值, 在各种情况下总是应该直接访问实例变量, 因为子类可能会 '覆写' 设置方法

(2) 另一个问题是 '惰性初始化', (即懒加载), 在这种情况下, 必须通过 getter 来访问属性, 否则实例变量就永远不会初始化, , 如果使用了 '懒加载', 就必须通过存取方法来访问属性

总结:

在对象内部读取数据时, 应该直接通过实例变量来读, 而写入数据时, 则应该通过 属性来写,

在初始化方法以及 dealloc 方法中, 总是应该直接通过实例变量来读写数据

在使用懒加载来初始化配置数据时, 需要通过属性来读取数据

04-15 13:30