25th,October,2015 JolieYang
基于Smalltalk设计,
有很多类似于Ruby、Python的动态特性,例如动态类型、动态加载、动态绑定等.
KVC(Key-Value-Code) 键值编码 对属性的
动态读写,提供了一种在
运行时而非编译时
动态访问对象属性与成员变量的方式(运行时确定属性的绑定),从而得到更灵活和易于重用的对象
.
优缺点
优点: 灵活性;易重用
缺点: 丢失了
编译时检查(不能对属性进行编译时检查);暴力的去get/set类的私有属性,
破坏类的封装性.
对象需要用
特定的方式来
命名方法.这种命名约定就称为键值编码.
命名规则:
动态设置属性 1.setA方法; 2. 成员变量_a; 3.成员变量a; 4.
这个类的setValue:forUndefinedKey
动态读取属性 1.a 方法(属性a的setter方法); 2.成员变量_a; 3. 成员变量a;4.valueforUndefinedKey:方法;
valueForKey 总是返回一个id对象,非对象的返回值会自动用NSValue或NSNumber封装.不能把非对象传给setValue:forKey:
Demo:
[cell setValue:@"intValue" forKey:@"property"];
[self
valueForKeyPath:@"department.name"];
keyPath版本更灵活,key版本速度稍快.
最佳实践:valueForKeyPath为调用者提供最大的灵活性;硬编码则使用valueForKey.
默认情况下KVC方法能够直接访问类的私有成员变量,如果我们不想这样,可以重写accessInstanceVariablesDirectly方法,并令其返回NO(默认是返回YES)。
高级技术:高阶消息传递 与 容器类操作符
高阶消息传递: NSArray *array = @[@"foo", @"bar", @"baz"];
NSArray *capitals = [array valueForKey:@"capitalizedString"];
备注:对于数组NSArray、集合NSSet,调用valueForKey:会对每个数组和集合成员调用valueForKey:,并返回新的数组或者集合。
容器类操作符:
NSArray *array = @[@"foo", @"bar", @"baz"];
NSUInteger totalLength = [[array valueForKeyPath:@"@sum.length"] intValue];
@sum是一个操作符,对指定的属性(length)求和.
KVO(Key-Value-Observing)键值观察
监听property的变化 通知某些对象(观察者)关于其他对象属性值发生变化的一种机制.
优缺点
优点:
性能好[开销相对于NSNotification和委托更小(只用存取方法来修改实例变量,不需要额外成本)];
容易实现视图组件和数据模型的分离,模型类的简洁;
缺点:回调方法中传递的代表变化的字典,用起来繁琐;bug难解决(会制造出人意料的代码执行路径,有一些代码运行但没有任何可见的代码说明行为发生的原因);
DEMO:
[self.object
addObserver:self forKeyPath:self.property options:0 context:(void *)self];// 添加监听对象(注册指定key路径的监听器)
[self.object
removeObserver:self forKeyPath: self.property];// 移除监听对象(删除指定keyPath的监听器)
- (void)
observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context // 回调监听
最佳实践: 尽量保守,简单的使用KVO; 在存在复杂相互依赖关系或者复杂的类继承层次的地方避免使用.
参考资料:
iOS开发系列--Objective-C之KVC、KVO
<<iOS编程实战>> 第22章
KVO/KVC 的概述与使用
iOS KVC & KVO
OC学习篇之---KVC和KVO操作
Key-Value Coding Programming Guide