iOS KVO使用方法

KVO(Key Value Observing)其实是一种观察者模式,利用它可以很容易实现视图组件和数据模型的分离,当数据模型的属性值改变之后作为监听器 的视图组件就会被激发,激发时就会回调监听器自身。在ObjC中要实现KVO则必须实现NSKeyValueObServing协议,不过幸运的是 NSObject已经实现了该协议,因此几乎所有的ObjC对象都可以使用KVO。

在ObjC中使用KVO操作常用的方法如下:

  • 注册指定Key路径的监听器: addObserver: forKeyPath: options: context:
  • 删除指定Key路径的监听器: removeObserver: forKeyPath、removeObserver: forKeyPath: context:
  • 回调监听: observeValueForKeyPath: ofObject: change: context:

KVO的使用步骤也比较简单:

  • 通过addObserver: forKeyPath: options: context:为被监听对象(它通常是数据模型)注册监听器
  • 重写监听器的observeValueForKeyPath: ofObject: change: context:方法
  • 推荐关注iOS开发:iOSDevTip

由 于我们还没有介绍过IOS的界面编程,这里我们还是在上面的例子基础上继续扩展,假设当我们的账户余额balance变动之后我们希望用户可以及时获得通 知。那么此时Account就作为我们的被监听对象,需要Person为它注册监听(使用addObserver: forKeyPath: options: context:);而人员Person作为监听器需要重写它的observeValueForKeyPath: ofObject: change: context:方法,当监听的余额发生改变后会回调监听器Person监听方法(observeValueForKeyPath:
ofObject: change: context:)。下面通过代码模拟上面的过程:

// Account.h

#import <Foundation/Foundation.h>

@interface Account : NSObject
#pragma mark - 属性
#pragma mark 余额
@property (nonatomic,assign) float balance;
@end
// Account.m

#import "Account.h"

@implementation Account

@end
// Person.h

#import <Foundation/Foundation.h>
@class Account;

@interface Person : NSObject{
    @private
    int _age;
}
#pragma mark - 属性
#pragma mark 姓名
@property (nonatomic,copy) NSString *name;
#pragma mark 账户
@property (nonatomic,retain) Account *account;

#pragma mark - 公共方法
#pragma mark 显示人员信息
-(void)showMessage;
@end
// Person.m

#import "Person.h"
#import "Account.h"

@implementation Person

#pragma mark - 公共方法
#pragma mark 显示人员信息
-(void)showMessage{
    NSLog(@"name=%@,age=%d",_name,_age);
}

#pragma mark 设置人员账户
-(void)setAccount:(Account *)account{
    _account=account;
    //添加对Account的监听
    [self.account addObserver:self forKeyPath:@"balance" options:NSKeyValueObservingOptionNew context:nil];
}

#pragma mark - 覆盖方法
#pragma mark 重写observeValueForKeyPath方法,当账户余额变化后此处获得通知
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
    if([keyPath isEqualToString:@"balance"]){//这里只处理balance属性
          NSLog(@"keyPath=%@,object=%@,newValue=%.2f,context=%@",keyPath,object,[[change  objectForKey:@"new"] floatValue],context);
    }
}
#pragma mark 重写销毁方法
-(void)dealloc{
    [self.account removeObserver:self forKeyPath:@"balance"];//移除监听
    //[super dealloc];//注意启用了ARC,此处不需要调用
}
@end
// main.m

#import <Foundation/Foundation.h>
#import "Person.h"
#import "Account.h"

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

        Person *person1=[[Person alloc]init];
        [email protected]"Kenshin";
        Account *account1=[[Account alloc]init];
        account1.balance=100000000.0;
        person1.account=account1;

        account1.balance=200000000.0;//注意执行到这一步会触发监听器回调函数observeValueForKeyPath: ofObject: change: context:
        //结果:keyPath=balance,object=<Account: 0x100103aa0>,newValue=200000000.00,context=(null)

    }
    return 0;
}

在上面的代码中我们在给人员分配账户时给账户的balance属性添加了监听,并且在监听回调方法中输出了监听到的信息,同时在对象销毁时移除监听,这就构成了一个典型的KVO应用。

时间: 2024-10-11 18:26:04

iOS KVO使用方法的相关文章

iOS KVO概述

iOS KVO概述 面试中经常会被问到:什么是KVO?这个问题既然出现概率这么大,那么我们就来详细讲一讲到底什么是KVO.下次再有面试官问你的时候,你就可以娓娓道来,以彰显高逼格 概述 问:什么是KVO? 答:KVO是Key-Value Observing的缩写.它提供一种机制,当指定的对象的属性被修改后,则对象就会接受到通知.简单的说就是每次指定的被观察的对象的属性被修改后,KVO就会自动通知相应的观察者了. 如果你能这样回答,面试官一定不会说你错的,这就是KVO的原理.但是如果你能说出KVO

ios kvo 简介

在一个复杂的,有状态的系统中,当一个对象的状态发生改变,如何通知系统,并对状态改变做出相应的行为是必需考虑的一个问题,在iOS中为这类问题提供了4种解决方法: 1. NSNotifiactaion和NSNotificationCenter:通知中心 2. Delegates:代理, 3. Callback:回调, 4. KVO(Key-Value Observing):键值观察 这篇文章就来说说通过KVO通知系统状态发生改变的用法. KVO是什么? KVO是Object-C中定义的一个通知机制,

ios KVO的实现原理

首先给大家介绍一下KVO的使用场景:当某个对象的某个属性改变的时候,需要我们做出相应的处理事件.比如我们自定义下拉刷新,那么我们是如何得知用户要进行的下拉刷新数据操作呢,我们可以监听控件的frame,通过用户下拉该控件的时候,会修改该控件的frame.y属性,我们使用KVO监听这个属性.当这个属性的y值在某个范围,我们认为是下拉刷新操作.我们可以去进行数据请求.因为现在下拉刷新的第三方框架有很多,所以很少有人关注下拉刷新的实现原理. 又比如,我们经常使用的网络请求的第三方AFN,它内部监听网络下

iOS 捕获未知方法的调用,避勉抛出异常

太阳火神的美丽人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致"创作公用协议 转载请保留此句:太阳火神的美丽人生 -  本博客专注于 敏捷开发及移动和物联设备研究:iOS.Android.Html5.Arduino.pcDuino,否则,出自本博客的文章拒绝转载或再转载,谢谢合作. NSObject 对象是 Objecitve-C 中的根类,其有以下两个方法,在调用 NSObject 及其子类的方法不存在时,会将这个调用封装成

iOS 常用公共方法

iOS常用公共方法 1. 获取磁盘总空间大小 //磁盘总空间 + (CGFloat)diskOfAllSizeMBytes{ CGFloat size = 0.0; NSError *error; NSDictionary *dic = [[NSFileManager defaultManager] attributesOfFileSystemForPath:NSHomeDirectory() error:&error]; if (error) { #ifdef DEBUG NSLog(@&quo

iOS 不定参数方法,类似UIAlertView的方法

//-------------------------- 方法申明 -------------------------- /** *  模仿UIAlertView方法 * *  @param argument 不定参数个数 */ - (void)copyAlertViewMethod:(id)argument, ... NS_REQUIRES_NIL_TERMINATION;//加了NS_REQUIRES_NIL_TERMINATION自动补齐功能就会自动在后面加nil //----------

【IOS】IOS开发问题解决方法索引(一)

IOS开发问题解决方法索引(一) 1       Xcode工程调试时无法命中断点的问题 若没有勾选LLVM Compiler 1.6 –> CodeGeneration –> Generate Debug Symbols 一项,则程序调试时无法命中断点. 2       Xcode调试时查看变量的几种方法 Xcode如何查看内存中的数据 http://blog.csdn.net/evgd2288/article/details/8995779 Xcode的Debug中查看数据细节的方法 ht

【IOS】IOS开发问题解决方法索引(二)

IOS开发问题解决方法索引(二) 1       不使用ARC编译,-fno-objc-arc ios5 选择了ARC但是不使用ARC编译,-fno-objc-arc http://leobluewing.iteye.com/blog/1384797 http://blog.cnrainbird.com/index.php/2012/03/13/object-c_kai_fa_zhong_hun_he_shi_yong_huo_bu_shi_yong_arc/ 2       SIGABRT错误

iOS: NSMutableArray的方法removeObject:inRange:

- (void)removeObject:(id)anObject inRange:(NSRange)aRange iOS: NSMutableArray的方法removeObject:inRange: