zoukankan      html  css  js  c++  java
  • KVO与KVC理解

    KVC 与 KVO 是 Objective C 的关键概念,个人认为必须理解的东西,下面是实例讲解。

    Key-Value Coding (KVC)

    KVC,即是指 NSKeyValueCoding,NSObject的一个category,提供一种机制来间接访问对象的属性。KVO 就是基于 KVC 实现的关键技术之一。

    一个对象拥有某些属性。比如说,一个 Person 对象有一个 name 和一个 address 属性。以 KVC 说法,Person 对象分别有一个 value 对应他的 name 和 address 的 key。 key 只是一个字符串,它对应的值可以是任意类型的对象。从最基础的层次上看,KVC 有两个方法:一个是设置 key 的值,另一个是获取 key 的值。如下面的例子:

     1 void changeName(Person *p, NSString *newName)
     2 {
     3  
     4     // using the KVC accessor (getter) method
     5     NSString *originalName = [p valueForKey:@"name"];
     6  
     7     // using the KVC  accessor (setter) method.
     8     [p setValue:newName forKey:@"name"];
     9  
    10     NSLog(@"Changed %@'s name to: %@", originalName, newName);
    11  
    12 }

    现在,如果 Person 有另外一个 key ——配偶(spouse),spouse 的 key 值是另一个 Person 对象,用 KVC 可以这样写:

     1 void logMarriage(Person *p)
     2 {
     3  
     4     // just using the accessor again, same as example above
     5     NSString *personsName = [p valueForKey:@"name"];
     6  
     7     // this line is different, because it is using
     8     // a "key path" instead of a normal "key"
     9     NSString *spousesName = [p valueForKeyPath:@"spouse.name"];
    10  
    11     NSLog(@"%@ is happily married to %@", personsName, spousesName);
    12  
    13 }

    key 与 key path 要区分开来,key 可以从一个对象中获取值,而 key path 可以将多个 key 用点号 “.” 分割连接起来,比如:

     1 [p valueForKeyPath:@"spouse.name"]; 

    相当于这样……

     1 [[p valueForKey:@"spouse"] valueForKey:@"name"]; 

    好了,以上是 KVC 的基本知识,接着看看 KVO。

    Key-Value Observing (KVO)

    Key-Value Observing (KVO) 建立在 KVC 之上,它能够观察一个对象的 KVC key path 值的变化。举个例子,用代码观察一个 person 对象的 address 变化,以下是实现的三个方法:

    • watchPersonForChangeOfAddress: 实现观察
    • observeValueForKeyPath:ofObject:change:context: 在被观察的 key path 的值变化时调用。
    • dealloc 停止观察
     1 static NSString *const KVO_CONTEXT_ADDRESS_CHANGED = @"KVO_CONTEXT_ADDRESS_CHANGED"
     2  
     3 @implementation PersonWatcher
     4  
     5 -(void) watchPersonForChangeOfAddress:(Person *)p
     6 {
     7  
     8     // this begins the observing
     9     [p addObserver:self
    10         forKeyPath:@"address"
    11            options:0
    12            context:KVO_CONTEXT_ADDRESS_CHANGED];
    13  
    14     // keep a record of all the people being observed,
    15     // because we need to stop observing them in dealloc
    16     [m_observedPeople addObject:p];
    17 }
    18  
    19 // whenever an observed key path changes, this method will be called
    20 - (void)observeValueForKeyPath:(NSString *)keyPath
    21                       ofObject:(id)object
    22                         change:(NSDictionary *)change
    23                        context:(void *)context
    24  
    25 {
    26     // use the context to make sure this is a change in the address,
    27     // because we may also be observing other things
    28     if(context == KVO_CONTEXT_ADDRESS_CHANGED) {
    29         NSString *name = [object valueForKey:@"name"];
    30         NSString *address = [object valueForKey:@"address"];
    31         NSLog(@"%@ has a new address: %@", name, address);
    32     }
    33 }
    34  
    35 -(void) dealloc;
    36 {
    37  
    38     // must stop observing everything before this object is
    39     // deallocated, otherwise it will cause crashes
    40     for(Person *p in m_observedPeople){
    41         [p removeObserver:self forKeyPath:@"address"];
    42     }
    43  
    44     [m_observedPeople release];
    45     m_observedPeople = nil;
    46  
    47     [super dealloc];
    48  
    49 }
    50  
    51 -(id) init;
    52 {
    53     if(self = [super init]){
    54         m_observedPeople = [NSMutableArray new];
    55     }
    56  
    57     return self;
    58 }
    59  
    60 @end

    这就是 KVO 的作用,它通过 key path 观察对象的值,当值发生变化的时候会收到通知。

    其他例子

    假设一个场景,股票的价格显示在当前屏幕上,当股票价格更改的时候,实时显示更新其价格。

    1.定义DataModel

    1 @interface StockData : NSObject {
    2     NSString * stockName;
    3     float price;
    4 }
    5 @end
    6 @implementation StockData
    7 @end

    2.定义此model为Controller的属性,实例化它,监听它的属性,并显示在当前的View里边。

     1 - (void)viewDidLoad
     2 {
     3     [super viewDidLoad];
     4 
     5     stockForKVO = [[StockData alloc] init];
     6     [stockForKVO setValue:@"searph" forKey:@"stockName"];
     7     [stockForKVO setValue:@"10.0" forKey:@"price"];    
     8     [stockForKVO addObserver:self forKeyPath:@"price" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:NULL];
     9 
    10     myLabel = [[UILabel alloc]initWithFrame:CGRectMake(100, 100, 100, 30 )];
    11     myLabel.textColor = [UIColor redColor];
    12     myLabel.text = [stockForKVO valueForKey:@"price"];
    13     [self.view addSubview:myLabel];
    14    
    15     UIButton * b = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    16     b.frame = CGRectMake(0, 0, 100, 30);
    17     [b addTarget:self action:@selector(buttonAction) forControlEvents:UIControlEventTouchUpInside];
    18     [self.view addSubview:b];
    19 
    20 }

    3.当点击button的时候,调用buttonAction方法,修改对象的属性。

    1 -(void) buttonAction
    2 {
    3     [stockForKVO setValue:@"20.0" forKey:@"price"];
    4 }

    4. 实现回调方法

    1 -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
    2 {
    3     if([keyPath isEqualToString:@"price"])
    4     {
    5         myLabel.text =[NSString stringWithFormat:@"%@",[stockForKVO valueForKey:@"price"]] ;6     }
    7 }

    5.增加观察与取消观察是成对出现的,所以需要在最后的时候,移除观察者

    1 - (void)dealloc
    2 {
    3     [super dealloc];
    4     [stockForKVO removeObserver:self forKeyPath:@"price"];
    5     [stockForKVO release];
    6 }

    转载自:http://magicalboy.com/kvc_and_kvo/

               http://blog.csdn.net/yuquan0821/article/details/6646400

  • 相关阅读:
    【HTML5 绘图与动画】使用canvas
    【H5新增元素和文档结构】新的全局属性 1. contentEditable 可编辑内容 2. contextmenu 快捷菜单 3. data 自定义属性 4. draggable 可拖动 5. dropzone 拖动数据 6. hidden 隐藏 7. spellcheck 语法检查 8. translate 可翻译
    【H5新增元素和文档结构】完善旧元素 1. a 超链接 2. ol 有序列表 3. dl 定义列表 4. cite 引用文本 5. small 小号字体 6. iframe 浮动框架 7. script 脚本
    【H5新增元素和文档结构】新的语义信息 1. address 2. time 3. figure 跟 figcaption 4. details 和 summary 5. mark 6. progress 7. meter 8. dialog 9.bdi 10. wbr 11. ruby、rt、rp 12. command
    【H5新增元素跟文档结构】新的文档结构 1. article 文章块 2. section 区块 3. nav 导航条 4. aside 辅助栏 5. main 主要区域 6. header 标题栏 7. hgroup 标题组 8. footer 页脚栏
    5_PHP数组_3_数组处理函数及其应用_9_数组集合运算函数
    【华为云技术分享】鲲鹏弹性云服务器GCC交叉编译环境搭建指南
    【华为云技术分享】7 分钟全面了解位运算
    【华为云技术分享】Linux内核编程环境 (1)
    【华为云技术分享】华为云MySQL 8.0正式商用,全新增强版开源利器强势来袭
  • 原文地址:https://www.cnblogs.com/novia/p/4501333.html
Copyright © 2011-2022 走看看