iOS--KVO

来源:互联网 发布:起点客户端数据 编辑:程序博客网 时间:2024/06/05 06:56

        KVO是iOS常用设计模式观察者模式的一种实现(还有一种“消息中心",小懒将于下次做讲解)。KVC是实现KVO的关键。


        ok,让我们先来了解下KVC。

KVC

    KVC是Key-Value-Coding的简称,它是一种可以直接通过字符串的名字(key)来访问类属性的机制。而不是通过调用Setter、Getter方法访问。
        主要用到的方法有:
获取值

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

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

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

  修改值

setValue:forKey:

setValue:forKeyPath:

setValue:forUndefinedKey:

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

  一对多关系成员的情况

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

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

        在此小懒就不用代码做介绍了,直接杀入KVO主题,前边也说过了KVC是实现KVO的技术关键,所以大家看KVO的代码即可。

KVO

        KVO,即:Key-Value- Observing,它提供一种机制,当指定的对象的属性被修改后,则对象就会接受到通知。

        举个例子,当前label的text是A类的一个字符串的值,在KVO的机制下,当我改变A类的字符串的值时label的text会相对应的改动,在此我并没有调用label的setter方法便间接的修改了label的text。说在这,相信大家肯定已经明白KVO的功能了。

        新建一个空的工程,创建RootViewController(继承UIViewcontroller)和Person(继承NSObject)类,并创建RootViewController的实例作为根视图。

        接下来我们将按照这三步具体的实现KVO:
        1. 注册,指定被观察者的属性,
        2. 实现回调方法
        3. 移除观察

        首先在person类中

#import <Foundation/Foundation.h>

@interface Person : NSObject

@property(nonatomic,copy)NSString *name;

@property(nonatomic,assign)NSInteger age;

@end

       
ok,我们只需要添加属性即可。

       RootViewController.h 做如下定义:

#import <UIKit/UIKit.h>
@class Person;

@interface RootViewController : UIViewController
{
    Person *_person;
    UILabel *_age;
}

@end

      
  "@class Person;",这种写法用于头文家中,以避免交叉导入(在.h中尽量使用@class,而在.m中使用#import)。
        
        RootViewController.m做如下定义:
修改viewdidLoad函数
- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    _person = [[Person alloc]init];
    [_person setValue:@"xiaolan" forKey:@"name"];
    [_person setValue:@"18" forKey:@"age"];
    //为_person添加高观察者,监听age属相.
    [_person addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionNew context:nil];
    
    //显示_person.name
    UILabel *name = [[UILabel alloc]initWithFrame:CGRectMake(30, 30, 60, 30)];
    [self.view addSubview:name];
    [name release];
    [name setText:_person.name];
    
    //显示_person.age
    _age = [[UILabel alloc]initWithFrame:CGRectMake(120, 30, 60, 30)];
    [self.view addSubview:_age];
    [_age release];
    _age.text = [_person valueForKey:@"age"];//kvc
    
    //修改_person.age
    UIButton *button = [[UIButton alloc]initWithFrame:CGRectMake(50, 80, 60, 30)];
    [self.view addSubview:button];
    [button release];
    [button setTitle:@"button" forState:UIControlStateNormal];
    [button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    [button setBackgroundColor:[UIColor redColor]];
    [button addTarget:self action:@selector(changeAge:) forControlEvents:UIControlEventTouchUpInside];
}

添加以下两个函数

-(void)changeAge:(UIButton *)sender
{
    [_person setValue:@"21" forKey:@"age"];
}

//实现回调方法
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if ([keyPath isEqualToString:@"age"]) {
        _age.text = [_person valueForKey:@"age"];//kvc
    }
}

因为小懒用的是mrc模式,所以要记得添加dealloc函数。
-(void)dealloc
{
    [super dealloc];
    [_person removeObserver:self forKeyPath:@"age"];
    [_person release];
}


Ok,到此便可以运行我们的程序看看KVO的效果了。
0 0