KVC and KVO KVB

1 篇文章 0 订阅



在传统的开发模式中,我们很容易陷入“胶水代码”的陷阱里。所谓的“胶水代码”,顾名思义,就是仅仅用来保持用户界面数据、状态同步的函数调用的集合体。这些函数调用扯不断,理还乱,并且使代码变的非常冗长、易出错、不易维护。

Cocoa提供了多个内部机制:Key-Value Coding(KVC)、Key-Value Observing(KVO)、Key-Value Binding(KVB)。这些机制通过规定了一组通用的Cocoa命名法则、调用规则等,实现了如下功能:

1. 
(KVC)
使用一对高度规范化的访问方法,获取以及设置任何对象的任何属性的值(所谓的属性既可以是个实实在在的成员变量,也可以是通过一对成员方法所抽象出的该对象的一个性质)。KVC提供了一种在运行时而非编译时动态访问对象属性与成员变量的方式,也就是说,我们可以用字符串的内容作为属性名称或者成员变量名称进行访问。这种特性有些类似于其他高级编程语言中的反射。
(KVO)
2. 通过继承一个特定的方法,并且指定希望监视的对象及希望监视的属性名称,就能在该对象的指定属性的值发生改变时,得到一个“通知”(尽管这不是一个真正意义上的通知),并且得到相关属性的值的变化(原先的值和改变后的新值)。KVO是Cocoa的一个重要机制,他提供了观察某一属性变化的方法,极大的简化了代码。这种观察-被观察模型适用于这样的情况,比方说根据A(数 据类)的某个属性值变化,B(view类)中的某个属性做出相应变化。对于推崇MVC的cocoa而言,kvo应用的地方非常广泛。(这样的机制听起来类 似Notification,但是notification是需要一个发送notification的对象,一般是 notificationCenter,来通知观察者。而kvo是直接通知到观察对象。
(KVB)
3. 通过一个简单的函数调用,使一个视图对象的一个指定属性随时随地都和一个控制器对象或模型对象的一个指定属性保持同步。一个开发者可以利用这些功能,将自己创建的类写的很范化、很通用,然后通过KVB将多个视图“绑定”到一个或多个控制器上,再将控制器绑定到最底层的数据模型上。这样一来,任何一个视图上的改变都会通过KVC被“压”到控制器里,然后又通过KVC从控制器“压”到数据模型里。当数据模型中的值发生改变时,一个或多个控制器又会得到KVO的“通知”,接着只要被绑定了的视图又会得到这一个或多个控制器的KVO“通知”。这样以来,开发者只需要在适当的时候告诉Cocoa,什么对象的什么值该和什么对象的什么值绑定,就可以了,其余数据更新、格式化等工作Cocoa都会替你完成。

二 .KVC

KVC支持类对象和内建基本数据类型。

 

获取值

valueForKey:,传入NSString属性的名字。

valueForKeyPath:,传入NSString属性的路径,xx.xx形式。

valueForUndefinedKey它的默认实现是抛出异常,可以重写这个函数做错误处理。

  修改值

setValue:forKey:

setValue:forKeyPath:

setValue:forUndefinedKey:

setNilValueForKey:当对非类对象属性设置nil时,调用,默认抛出异常。

  一对多关系成员的情况

mutableArrayValueForKey:有序一对多关系成员  NSArray

mutableSetValueForKey:无序一对多关系成员  NSSet

 

三,实例:

#import <Foundation/Foundation.h>

@interface Product : NSObject

@property NSString* name;

@end

@implementation Product

@synthesize name = _name;

- (void)dealloc

{

    self.name = nil;

  }

@end

@interface Manufacturer : NSObject

@property Product* product;

@end

@implementation Manufacturer

@synthesize product = _product;

-(void)dealloc

{

    self.product = nil;

}

@end

int main(int argc, const char * argv[])

{

    

    

    @autoreleasepool

    {

        Manufacturer* apple = [[Manufacturer alloc] init];

        Product* iPhone4S = [[Product alloc] init];

        iPhone4S.name = @"iPhone 4S";

        apple.product = iPhone4S;

        

        Manufacturer* micro$oft = [[Manufacturer alloc] init];

        Product* win8 = [[Product alloc] init];

        win8.name = @"Windows 8";

        micro$oft.product = win8;

        

        NSLog(@"productName:\n%@\n%@", [win8 valueForKey:@"name"],[[apple valueForKey:@"product"] valueForKey:@"name"]);

        

        NSArray* manufacturerArray = [NSArray arrayWithObjects:apple, micro$oft, nil];

        

        NSArray* productNameArray = [manufacturerArray valueForKeyPath:@"product.name"];

        NSLog(@"productNameArray:\n%@", productNameArray);

        

    }

    return 0;

}


三 .KVO使用方法

Key Value Observing, 顾名思义就是一种observer 模式用于监听property的变化,KVO跟NSNotification有很多相似的地方, 用addObserver:forKeyPath:options:context:去start observer, 用removeObserver:forKeyPath:context去stop observer, 回调就是observeValueForKeyPath:ofObject:change:context:。
 
   
   
  1. - (void)removeObservation { 
  2.     [self.object removeObserver:self 
  3.                      forKeyPath:self.property]; 
  4.   
  5. - (void)addObservation { 
  6.     [self.object addObserver:self forKeyPath:self.property 
  7.                      options:0 
  8.                      context:(__bridge void*)self]; 
  9.   
  10. - (void)observeValueForKeyPath:(NSString *)keyPath 
  11.                       ofObject:(id)object 
  12.                         change:(NSDictionary *)change 
  13.                       context:(void *)context { 
  14.   if ((__bridge id)context == self) { 
  15.     // 只处理跟我们当前class的property更新 
  16.   } 
  17.   else { 
  18.     [super observeValueForKeyPath:keyPath ofObject:object 
  19.                            change:change context:context]; 
  20.   } 
 
对于KVO来说,我们要做的只是简单update 我们的property数据,不需要像NSNotificationCenter那样关心是否有人在监听你的请求,如果没有人监听该怎么办, 所有addObserver, removeObserver, callback 都是想要监听的你的property的class做的事情。 曾经做个项目,用NSNotificationCenter post Notification在一个network callback里面,可是这时候因为最早的addObserver的class被释放了, 接着生成的addObserver的class, 就接受到了上一个observer该监听的事件,所以造成了错误,那时候的解决方案是为addObserve key做unique,不会2次addObserver 的key是相同的,但是有了KVO, 我们同样可以用KVO来完成,当addOberver的的object remove的时候,就不会有这样的callback被调用了。


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值