现在的位置: 首页 > 综合 > 正文

关于KVC–KVO–KVB

2013年07月24日 ⁄ 综合 ⁄ 共 4481字 ⁄ 字号 评论关闭

概述:都是以[KVC]key-Value Coding   为基础 

Key-Value Coding(KVC)实现分析

    KVC运用了一个isa-swizzling技术。isa-swizzling就是类型混合指针机制。KVC主要通过isa- swizzling,来实现其内部查找定位的。isa指针,如其名称所指,(就是is a kind of的意思),指向维护分发表的对象的类。该分发表实际上包含了指向实现类中的方法的指针,和其它数据。

    比如说如下的一行KVC的代码:

[site setValue:@"sitename" forKey:@"name"];



就会被编译器处理成:

SEL sel = sel_get_uid ("setValue:forKey:");

IMP method = objc_msg_lookup (site->isa,sel);

method(site, sel, @"sitename", @"name");



首先介绍两个基本概念:

    (1)SEL数据类型:它是编译器运行Objective-C里的方法的环境参数。

    (2)IMP数据类型:他其实就是一个 编译器内部实现时候的函数指针。当Objective-C编译器去处理实现一个方法的时候,就会指向一个IMP对象,这个对象是C语言表述的类型(事实 上,在Objective-C的编译器处理的时候,基本上都是C语言的)。

这下KVC内部的实现就很清楚的清楚了:一个对象在调用setValue的时候,(1)首先根据方法名找到运行方法的时候所需要的环境参 数。(2)他会从自己isa指针结合环境参数,找到具体的方法实现的接口。(3)再直接查找得来的具体的方法实现。

Key-Value Observing机制的概述

Key-Value Observing (简写为KVO):当指定的对象的属性被修改了,允许对象接受到通知的机制。每次指定的被观察对象的属性被修改的时候,KVO都会自动的去通知相应的观察 者。

KVO的优点

当有属性改变,KVO会提供自动的消息通知。这样的架构有很多好处。首先,开发人员不需要自己去实现这样的方案:每次属性改变了就发送消息通知。这 是KVO机制提供的最大的优点。因为这个方案已经被明确定义,获得框架级支持,可以方便地采用。开发人员不需要添加任何代码,不需要设计自己的观察者模 型,直接可以在工程里使用。其次,KVO的架构非常的强大,可以很容易的支持多个观察者观察同一个属性,以及相关的值。

KVB

两个基本方法

1:为对象添加观察者OBserver
addObserver:forKeyPath:options:context: 


2:观察者OBserver收到信息的处理函数
observeValueForKeyPath:ofObject:change:context: 

使用步骤如下:
1. 注册,指定被观察者的属性,
2. 实现回调方法
3. 触发回调方法
4. 移除观察

KVO使用例子代码如下:
###############Model(模型)###############
#import <Foundation/Foundation.h>
@interface Music : NSObject {
    //
监听的属性

    NSString *musicName;
}
@end

#import "Music.h"
@implementation Music
@end

###############ViewController(视图控制器)###############
#import <UIKit/UIKit.h>
@class Music;
@interface ViewController : UIViewController {
    Music
*music;
   
}
@property (nonatomic, retain) Music *music;
@end

@implementation ViewController
@synthesize music;

#pragma mark - View lifecycle

- (void)viewDidLoad
{
    [super
viewDidLoad];

   
    music
= [[Music alloc] init];

   
    //
添加观察者  注册当属性发生改变的时候被调用的

    [music
addObserver:self forKeyPath:@"musicName" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];

   
    //
UILabel控件

    UILabel
*musicLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 150, 280, 21)];

    musicLabel.font
= [UIFont fontWithName:@"ArialMT" size:18];

    musicLabel.textColor
= [UIColor redColor];

    musicLabel.tag
= 100;

    [self.view
addSubview:musicLabel];

    [musicLabel
release];

   
    //
UITextField控件

    UITextField
*musicTextField = [[UITextField alloc] initWithFrame:CGRectMake(20, 200, 280, 21)];

    musicTextField.font
= [UIFont fontWithName:@"ArialMT" size:18];

    musicTextField.placeholder
= @"Please enter some words.";

    musicTextField.backgroundColor
= [UIColor whiteColor];

   
    //
UITextField输入内容时候调用

    [musicTextField
addTarget:self action:@selector(textFieldDidChange:) forControlEvents:
UIControlEventEditingChanged];
   
    [self.view
addSubview:musicTextField];

    [musicTextField
release];

    self.view.backgroundColor
= [UIColor grayColor];

}

- (void)textFieldDidChange:(id)sender {
    UITextField
*textField = (UITextField *)sender;

    NSLog(@">>>>>>>>>>>>>>>%@",textField.text);
    // 修改正在监听的属性,将调用下面回调方法
    [music
setValue:textField.text forKey:@"musicName"];

}

// 只要Music类的"musicName"属性发生的变化都会触发到以下的方法
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    UILabel
*label = (UILabel *)[self.view viewWithTag:100];

    //
如果改变的属性是"musicName"

    if
(
[keyPath isEqualToString:@"musicName"])
{

        //
将 
当前的musicName属性的值 赋值给UILabel
        label.text
[music valueForKey:@"musicName"];
        //
输出
改变前的值
        NSLog(@"old
musicName is %@",
[change objectForKey:@"old"]);
        //
输出
改变后的值
        NSLog(@"new
musicName is %@",
[change objectForKey:@"new"]);
 
      
    }
}

#pragma mark - Memory Management
- (void)dealloc {
    //
移除观察者

    [music
removeObserver:self forKeyPath:@"musicName"];

    [music
release];

    [super
dealloc];

}

-------------------------------------------------------------------


MVC架构是"Model-View-Controller"的缩写,中文翻译为"模式-视图-控制器"。MVC应用程序总是由这三个部分组成。 Event(事件)导致Controller改变Model或View,或者同时改变两者。只要Controller改变了Models的数据或者属性, 所有依赖的View都会自动更新。类似的,只要Controller改变了View,View会从潜在的Model中获取数据来刷新自己。

  MVC架构最早是smalltalk语言研究团提出的,应用于用户交互应用程序中。

  MVC模式是一个复杂的架构模式,其实现也显得非常复杂。但是,我们已经总结出了很多可靠的设计模式,多种设计模式结合在一起,使MVC模式的 实现变得相对简单易行。Views可以看作一棵树,显然可以用Composite Pattern来实现。Views和Models之间的关系可以用Observer Pattern体现。Controller控制Views的显示,可以用Strategy Pattern实现。Model通常是一个调停者,可采用Mediator
Pattern来实现。


KVC--KVO--KVB优势

这些机制通过规定了一组通用的Cocoa命名法则、调用规则等,实现了如下功能:

   1. 使用一对高度规范化的访问方法,获取以及设置任何对象的任何属性的值(所谓的属性既可以是个实实在在的成员变量,也可以是通过一对成员方法所抽象出的该对 象的一个性质)。
   2. 通过继承一个特定的方法,并且指定希望监视的对象及希望监视的属性名称,就能在该对象的指定属性的值发生改变时,得到一个“通知”(尽管这不是一个真正意 义上的通知),并且得到相关属性的值的变化(原先的值和改变后的新值)。
   3. 通过一个简单的函数调用,使一个视图对象的一个指定属性随时随地都和一个控制器对象或模型对象的一个指定属性保持同步。

抱歉!评论已关闭.