IOS Key-Value Observing (KVO)

  kvo,与观察者模式类似,通过给指定的对象设置观察者,来检测对象的变化,当指定的对象的属性被修改后,用于作为观察者的对象会接收到通知。简单的说就是每次指定的被观察的对象的属性被修改后,kvo就会自动通知相应的观察者。系统框架已经支持kvo,所以在开发过程中可以直接使用,非常方便。

一、kvo的使用步骤

1、注册,指定被观察者的属性

2、实现回调方法

3、移除观察

二、通过现实中的小例子介绍一下kvo的用法

  我有一张银行卡,只要卡内的金额发生的改变,银行就会发短信给我提示,下面通过代码使用kvo来模拟一下这个过程

  先创建一个Card银行卡类,卡里有money金额的属性,在初始化这张卡的时候,给卡里金额设置一个初值1000,然后每隔1秒钟模拟消费10元,代码如下:

  Card.h

//  Card.h
//  KVO
//
//  Created by jerei on 15-6-5.
//  Copyright (c) 2015年 jerehedu. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface Card : NSObject

@property (nonatomic, assign) float money;

@end

  Card.m

//  Card.m
//  KVO
//
//  Created by jerei on 15-6-5.
//  Copyright (c) 2015年 jerehedu. All rights reserved.
//

#import "Card.h"

@implementation Card

-(instancetype)init
{
    if (self = [super init]) {
        _money = 1000.0;

        [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(changeMoney) userInfo:nil repeats:YES];
    }
    return self;
}

//改变卡内金额
-(void)changeMoney
{
    self.money -= 10;
}

@end

  再创建一个People人类,在这个类中有姓名name和card银行卡两个属性。

  People.h

//  People.h
//  KVO
//
//  Created by jerei on 15-6-5.
//  Copyright (c) 2015年 jerehedu. All rights reserved.
//

#import <Foundation/Foundation.h>

@class Card;

@interface People : NSObject

@property (nonatomic, copy) NSString *name;
@property (nonatomic, strong) Card *card;

-(id)initWithName:(NSString *)name andCard:(Card *)card;

@end

  People.m

//  People.m
//  KVO
//
//  Created by jerei on 15-6-5.
//  Copyright (c) 2015年 jerehedu. All rights reserved.
//

#import "People.h"
#import "Card.h"

@implementation People

-(id)initWithName:(NSString *)name andCard:(Card *)card
{
    if (self = [super init]) {
        _name = name;
        _card = card;
    }

    return self;
}

@end

  创建好了两个类之后,在People类中通过kvo来监测银行卡中金额的变化

1、人需要监听银行账户中的金额,需要注册监听对象

- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context;

  调用方法的是被监听的对象,参数分别为:

addObserver:观察者

forKeyPath:被监听的对象的属性,属性里面还有属性的,可以用点语法

options:想监听的对象是什么操作,比如初始化、有新的值

context:上下文,一般为nil,当KeyPath:相同时,可以用它来区分

  因此,在People.m中需要添加的代码为:

-(id)initWithName:(NSString *)name andCard:(Card *)card
{
    if (self = [super init]) {
        _name = name;
        _card = card;

        //注册,添加观察者
        [_card addObserver:self forKeyPath:@"money" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
    }

    return self;
}

2、一旦注册了,就可以去回调函数中感知变化过程

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;

observeValueForKeyPath:字符串,被监听的属性

ofObject:哪一个对象被监听

change:字典,包含了变化前和变化后的值

context:上下文

  因此,在People.m中需要实现回调方法

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    NSLog(@"回调方法 %@",change);
}

3、解除监听对象

- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath;

  调用方法的是被监听的对象

removeObserver:观察者

forKeyPath:字符串

  因此,在People.m中重写dealloc方法,实现移除监听者

-(void)dealloc
{
    [_card removeObserver:self forKeyPath:@"money"];
}

4、ps: kvo属性值改变时,不能直接改值

  例子中Card类中有一个changeMoney方法,在这个方法中修改了被监听属性的值,下面介绍4中方法给大家。

-(void)changeMoney
{
    //不能直接改值!!!!
    _money -= 10; //错误的

    //1.点语法
    self.money -= 10;

    //2. set方法
    float f = _money-10;
    [self setMoney:f];

    //3. kvc
    [self setValue:@(f) forKey:@"money"];

    //4.
    [self willChangeValueForKey:@"money"];
    _money -= 10;
    [self didChangeValueForKey:@"money"];

}

时间: 2024-10-21 01:38:51

IOS Key-Value Observing (KVO)的相关文章

iOS开发——实用篇&amp;KVO与KVC详解

KVO与KVC详解 由于ObjC主要基于Smalltalk进行设计,因此它有很多类似于Ruby.Python的动态特性,例如动态类型.动态加载.动态绑定等.今天我们着重介绍ObjC中的键值编码(KVC).键值监听(KVO)特性: 键值编码KVC 键值监听KVO 键值编码KVC 我们知道在C#中可以通过反射读写一个对象的属性,有时候这种方式特别方便,因为你可以利用字符串的方式去动态控制一个对象.其实由于ObjC的语言特性,你根部不必进行任何操作就可以进行属性的动态读写,这种方式就是Key Valu

iOS开发-KVC和KVO的理解

KVC和KVO看起来很专业,其实用起来还是比较简单的,KVC(Key-value coding)可以理解为键值对编码,如果对象的基本类型,那么键值对编码实际上和get,set方法没有区别,如果是属性是另外一个对象,那么发现KVC用起来还是非常顺手,KVO(key-value observing)是键值对的观察者模式,如果对象的属性发生变更,那么会触发observeValueForKeyPath事件,KVO的这种通知特性让我们在开发的时候节省了不必要的代码,提高了开发效率. KVC键值对编码 KV

【转载】iOS中delegate,notification,KVO三种模式实现通信的优缺点

原帖地址:http://blog.csdn.net/yangxt/article/details/8176636 在开发iOS中,有三种模式来实现controller之间的通信: 1.委托delegation: 2.通知中心Notification Center: 3.键值观察key value observing,KVO 因此,那为什么我们需要这些模式以及什么时候用它以及什么时候不用它. 1.delegate 基本特征: 一 个controller定义了一个协议(即一系列的方法定义).该协议描

iOS 中KVC、KVO、NSNotification、delegate 总结及区别

iOS 中KVC.KVO.NSNotification.delegate 总结及区别 1.KVC,即是指 NSKeyValueCoding,一个非正式的Protocol,提供一种机制来间接访问对象的属性.而不是通过调用Setter.Getter方法访问.KVO 就是基于 KVC 实现的关键技术之一. Demo: @interface myPerson : NSObject { NSString*_name; int      _age; int      _height; int      _w

IOS开发——UI基础-KVO

KVO == Key Value Observing 作用: 可以监听某个对象属性的改变 一.使用KVO Person *p = [Person new]; p.name = @"chg"; p.age = 30; // 给p这个对象添加一个监听 , 监听p对象的age属性的改变, 只要age属性改变就通知self [p addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionOld |

【iOS】KVC 与 KVO

一.KVC与KVO *"KVC":key value Coding(键值编码) *目的:间接的修改或获取对象的属性,降低程序(类与类)之间的耦合度. *"KVO":key value Observer(键值观察),观察者模式.(检测模型变化用的多) *目的:通常用于观察某个对象的某个属性发生变化时,及时做出相应. 二.KVC的使用方式 KVC被称为iOS开发平台的大招!!! 能快速修改对象属性. *[p1setValue:@"xxxx"forKe

【iOS】KVC 和 KVO 的使用场景

http://blog.csdn.net/chenglibin1988/article/details/38259865 Key Value Coding Key Value Coding是cocoa的一个标准组成部分,它能让我们可以通过name(key)的方式访问property, 不必调用明确的property accssor, 如我们有个property叫做foo, 我们可以foo直接访问它,同样我们也可以用KVC来完成[Object valueForKey:@“foo”], 有同学就会问

KVO(Key Value Observing),是观察者模式在Foundation中的实现。

KVO的原理 简而言之就是: 1.当一个object有观察者时,动态创建这个object的类的子类 2.对于每个被观察的property,重写其set方法 3.在重写的set方法中调用- willChangeValueForKey:和- didChangeValueForKey:通知观察者 4.当一个property没有观察者时,删除重写的方法 5.当没有observer观察任何一个property时,删除动态创建的子类 空说无凭,简单验证下. @interface Sark : NSObjec

iOS 错误:… is being deallocated while key value observing are still registered with it

这个错误从字面上来看就是有一个实例由于被observing而无法被释放. 具体原因可能是该对象添加了一个oberver.所以释放的时候要先取消observer. 具体方法是在 dealloc 方法中: - (void)dealloc { [object removeObserver:self forKeyPath:@"aPath"]; } ARC 下不能调用 super 的 dealloc 方法.