IOS SDK详解之KVO

原创Blog,转载请注明出处

blog.csdn.net/hello_hwc



前言:KVC和KVO是帮助我们驾驭objective C动态特性工具。KVO是建立在KVC基础上的,所以不了解KVC的同学可以参见我的这篇博客。这里我不会再重复讲解KVC。

http://blog.csdn.net/hello_hwc/article/details/43769765

本文的内容

KVO的定义

KVO的典型使用场景。

手动KVO

几点KVO要说的地方


一 KVO的定义

KVO提供了一种key-value-observing的机制,也就是说可以通过监听key,来获得value的变化。用来在对象之间监听状态变化。使用KVO的类要遵循 协议,事实上,任何继承自NSObject的类,都遵循了这个协议。而Object C中,几乎所有的类都源自NSObject

使用KVO通常分为三步

1.1 订阅想要监听的keypath

用函数

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

注册通知

  • observer:观察者,也就是KVO通知的订阅者。订阅着必须实现

    observeValueForKeyPath:ofObject:change:context:方法

  • keyPath:描述将要观察的属性,相对于被观察者。
  • options:KVO的一些属性配置;有四个选项。
  • context: 上下文,这个会传递到订阅着的函数中,用来区分消息,所以应当是不同的。

options所包括的内容

  • NSKeyValueObservingOptionNew:change字典包括改变后的值
  • NSKeyValueObservingOptionOld:change字典包括改变前的值
  • NSKeyValueObservingOptionInitial:注册后立刻触发KVO通知
  • NSKeyValueObservingOptionPrior:值改变前是否也要通知(这个key决定了是否在改变前改变后通知两次)

1.2 响应状态变化

每当监听的keyPath发生变化了,就会在这个函数中回调。

- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context
  • keyPath:被监听的keyPath , 用来区分不同的KVO监听。
  • object: 被观察修改后的对象(可以通过object获得修改后的值)
  • change:保存信息改变的字典(可能有旧的值,新的值等)
  • context:上下文,用来区分不同的KVO监听。

1.3 在适当的时候,取消订阅

通常使用两个函数

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

一般在remove的时候会这么写,因为remove的时候,无法判读啊remove是否成功了

    @try {
        [object removeObserver:self forKeyPath:keyPath];
    }
    @catch (NSException *exception) {
        NSLog(@"%@",exception);
    }

二 KVO的典型使用场景 - model 与 view的同步

这里,你将看到一个完整的KVO的例子。和上篇KVC一样,我写了个类似的demo。点击random会随机改变User的age,然后UI上要进行同步显示出新的和旧的age。

实现过程如下:

定义了一个User类来作为Model

@interface User : NSObject
@property (strong,nonatomic) NSString * name;
@property (nonatomic) NSUInteger age;
@end

定义两个静态的变量,一个作为keyPath,一个作为context

static  NSString * observename = @"age";
static void * privateContext = 0;

然后在viewWillAppear中注册(订阅)KVO,在viewWillDisappear中删除KVO

-(void)viewWillAppear:(BOOL)animated{
    [self.user addObserver:self
                forKeyPath:observename
                   options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:privateContext];
}
-(void)viewWillDisappear:(BOOL)animated{
    @try {
        [self.user removeObserver:self forKeyPath:observename];
    }
    @catch (NSException *exception) {
        NSLog(@"%@",exception);
    }
}

当点击random的时候,age会改变

- (IBAction)random:(id)sender {
    self.user.age = arc4random()%100 +1;
}

然后,在上面提到的函数中进行model和view的同步

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
    if (context == privateContext) {
        if ([keyPath isEqualToString:observename]) {
            NSNumber * old = [change objectForKey:NSKeyValueChangeOldKey];
            NSNumber * new = [change objectForKey:NSKeyValueChangeNewKey];
            self.lastvalue.text = [NSString stringWithFormat:@"%@",old];
            self.newvalue.text = [NSString stringWithFormat:@"%@",new];
        }
    }
}

三 手动KVO

KVO的实现,是对注册的keyPath中自动实现了两个函数,在Setter中,自动调用。

- (void)willChangeValueForKey:(NSString *)key
- (void)didChangeValueForKey:(NSString *)key

可能有时候,我们要实现手动的KVO

这时候需要关闭自动生成KVO通知,然后手动的调用,手动通知的好处就是,可以灵活加上自己想要的判断条件。例如

+(BOOL)automaticallyNotifiesObserversOfAge{
    return NO;
}
-(void)setAge:(NSUInteger)age{
    if (age < 22) {
        return;
    }
    [self willChangeValueForKey:@"age"];
    _age = age;
    [self didChangeValueForKey:@"age"];
}

四 KVO要提到的几点

KVO和Context

由于Context通常用来区分不同的KVO,所以context的唯一性很重要。通常,我的使用方式是通过在当前.m文件里用静态变量定义。

static void * privateContext = 0;

KVO与线程

KVO的响应和KVO观察的值变化是在一个线程上的,所以,大多数时候,不要把KVO与多线程混合起来。除非能够保证所有的观察者都能线程安全的处理KVO

监听变化的值

改变前和改变后分别为

id oldValue = change[NSKeyValueChangeOldKey];
id newValue = change[NSKeyValueChangeNewKey];

时间: 2024-11-03 21:09:11

IOS SDK详解之KVO的相关文章

iOS SDK详解之NSScanner-分析String

原创blog,转载请注明出处 blog.csdn.net/hello_hwc 欢迎关注我的iOS SDK详解专栏,这里有很多基础的文章 http://blog.csdn.net/column/details/huangwenchen-ios-sdk.html 前言:NSScanner是分析String,把String转为substring和数字的很好的工具.它使用一个NSString初始化,使用的时候通常从开头处扫描直到结尾. 本文会先举出两个例子,然后详细的讲解NSScanner的方法.源码是

iOS SDK详解之NSCoding协议

原创blog,转载请注明出处 http://blog.csdn.net/hello_hwc?viewmode=contents 欢迎关注我的iOS SDK详解专栏 http://blog.csdn.net/column/details/huangwenchen-ios-sdk.html 前言:NSCoding是对iOS中的Model类进行编码和解码必须要遵循的协议,如果一个对象要被归档,那么这个协议是必须的. NSCoding要实现两个方法 - initWithCoder: //解码 - enc

IOS SDK详解

来源:http://blog.csdn.net/column/details/huangwenchen-ios-sdk.html?page=1#42803301 博客专栏>移动开发专栏>IOS SDK详解 分享到:新浪微博腾讯微博IOS SDK详解 本专栏从IOS SDK中常用的Framework出发,继而深入的介绍各个Framework.每个Framework博主都会进行Demo 收藏 订阅 最新更新文章 [移动开发] IOS SDK详解之CALayer(二) 原创Blog,转载请注明出处

iOS SDK详解之IBInspectable和IB_DESIGNABLE-Storyboad动态刷新

原创Blog,转载请注明出处 blog.csdn.net/hello_hwc 欢迎关注我的iOS-SDK详解专栏,在这里你能找到很多iOS开发基础的文章 http://blog.csdn.net/column/details/huangwenchen-ios-sdk.html 前言: 在做应用的UI设计的时候,如果属性能够在Interface Builder的图形化界面进行设置,并且动态的预览到效果,那样无疑会大大提高应用的开发效率.而XCode为我们提供了这样的一种方式,就是使用IBInspe

iOS SDK详解之NSCalendar &amp; NSDate?Components

原创Blog,转载请注明出处 blog.csdn.net/hello_hwc 欢饮关注我的iOS SDK详解专栏 http://blog.csdn.net/column/details/huangwenchen-ios-sdk.html 前言:NSCalendar 和 NSDate?Components是有关iOS 时间相关API很重要的两个类.最近刚好用到,这里就整理下. 概念 NSCalendar 顾名思义就是日历,封装了系统如何按照年月日的方式来组织时间,组织时间的方式和地区,时区有很大关

IOS SDK详解之KVC

原创Blog,转载请注明出处 blog.csdn.net/hello_hwc 前言:本文的架构 KVC的定义 KVC的几个场景 希望,通过本文让不了解KVC的同学入门,KVC在IOS开发中是个比较重要的概念,也是理解KVO的基础. 一 KVC的定义 KVC的全称是key-value coding,通过key-value的方式来访问属性.在很多地方,KVC是非常方便的. 属性 @property (strong,nonatomic) NSString * message; 赋值 [self set

IOS SDK详解之NSDictionary

原创Blog,转载请注明出处 blog.csdn.net/hello_hwc 前言:本文将要讲述的内容有 1.NSDictionary 以及 NSMutableDictionary 概述 2.常用属性方法举例(不常用的本文不会涉及) 一 NSDictionary/NSMutableDictionary概述 NSDictionary提供了一种key-value的数据存储方式.总的来说,任何对象都可以作为key,只要其遵循NSCopying协议.其中,key不能相同(由isEqual来判断).key

iOS SDK详解之模糊(毛玻璃)效果效果

原创blog,转载请注明出处 http://blog.csdn.net/hello_hwc?viewmode=list 前言: 在iOS 8 之前,想要实现模糊效果,一般会使用一些Github库,当然自己定制也可以,其原理就是用Core Image进行一些数字图像处理(因为电子出身,本课的时候做过,用矩阵来做).不过,到了iOS 8之后,这一切变的非常简单,因为Apple公开了之前的几个私有API. Demo效果 三种Blur Vibrancy(也就是在Blur上加一些想要强调的部分) Demo

IOS SDK详解之沙盒(一)图解+小工具

原创Blog,转载请注明出处 blog.csdn.net/hello_hwc 前言: IOS沙盒机制限制了App的访问权限,进而保护用户的数据信息. 一 查看沙盒结构 和一些百度来的博客显示隐藏稳文件的方式不同,本文也提供两种方式,简单粗暴. 方式一 使用工具simpholders(推荐) 下载链接 http://simpholders.com/ 效果如图 方式二 直接使用代码 用以下代码,log出documents/路径 NSURL * url = [[[NSFileManager defau