zoukankan      html  css  js  c++  java
  • Objective-C语法之KVO的使用

    简介:

    上篇我们讲到了KVC,这篇我们学习KVO,全名为:Key Value Observing,直译为:基于键值的观察者。

    那它有什么用呢?KVO主要用于视图交互方面,比如界面的某些数据变化了,界面的显示也跟着需要变化,那就要建立数据和界面的关联。

    ObjC中提供的KVO就是解决这种问题的。以下用显示页面观察学生的课程名称变化的例子来说明KVO的使用。

    学生类命名为:Student,页面类是:PageView.

    上图来自苹果官网:图中的BankObject好比PageView,PersonObject好比Student,

    PageView观察Student的变化。

    1、添加Student学生类。

    .h

    复制代码
    #import <Foundation/Foundation.h>
    @interface Student : NSObject
    {
        NSString *name;
        NSString *courseName;
    }
    -(void)changeCourseName:(NSString*) newCourseName;
    @end
    复制代码

    类中有name,和课程名称courseName,添加一个可以改变课程名称的方法changeCourseName。一会用来做对比,看直接改变课程名称时会不会有回调。

    实现文件.m

    复制代码
    #import "Student.h"
    
    @implementation Student
    -(void)changeCourseName:(NSString*) newCourseName
    {
        courseName = newCourseName;
    }
    @end
    复制代码

    实现类把方法实现了。

    2、页面类实现

    .h文件

    复制代码
    #import <Foundation/Foundation.h>
    @class Student;
    @interface PageView : NSObject
    {
        Student *student;
    }
    -(id)init:(Student*)initStudent;
    @end
    复制代码

    .m文件

    复制代码
    #import "PageView.h"
    #import "Student.h"
    
    @implementation PageView
    -(id)init:(Student*)initStudent
    {
        if (self = [super init]) {
            student = initStudent;
            [student addObserver:self 
                      forKeyPath:@"courseName" 
                         options:NSKeyValueObservingOptionOld
                                |NSKeyValueObservingOptionNew context:nil];
        }
        return self;
    }
    
    - (void) dealloc{ 
        [student removeObserver:self forKeyPath:@"courseName" context:nil];
        [super dealloc]; 
    }
    
    -(void)observeValueForKeyPath:(NSString *)keyPath 
                         ofObject:(id)object 
                           change:(NSDictionary *)change 
                          context:(void *)context
    {
        if ([keyPath isEqual:@"courseName"]) {
            NSLog(@"PageView课程被改变了");
            NSLog(@"PageView新课程是:%@ 老课程是:%@", [change objectForKey:@"new"],[change objectForKey:@"old"]);
        }
    }
    @end
    复制代码

    init初始化时,向student实例添加观察者,在释放的时候移除观察者。

    3、实现观察

    在main函数中

    复制代码
    #import "Student.h"
    #import "Course.h"
    #import "PageView.h"
    
    int main(int argc, const char * argv[])
    {
        @autoreleasepool {
            Student *student = [[[Student alloc]init]autorelease];
            [student changeCourseName:@"数学课"];
            NSLog(@"初始值:%@", [student valueForKey:@"courseName"]);
            
            //创建页面实例
            PageView *pageview = [[[PageView alloc]init:student]autorelease];
            
            [student setValue:@"化学课" forKey:@"courseName"];
          
        }
        return 0;
    }
    复制代码

    新建一个student的实例,设置他的课程是数学课,然后创建页面类的时候,用student初始化。这是页面类已经观察着学生的课程了。

    再给课程设置新的值为化学课。这时候运行打印结果:

    2012-07-24 16:29:21.561 objectiveC[2192:403] 初始值:数学课

    2012-07-24 16:29:21.565 objectiveC[2192:403] PageView课程被改变了

    2012-07-24 16:29:21.566 objectiveC[2192:403] PageView新课程是:化学课 老课程是:数学课

    可以看到Pageview类中的回调被调用,Pageview接收到学生课程数据更新的信息。

    4、直接改变课程信息对比

    复制代码
    #import "Student.h"
    #import "Course.h"
    #import "PageView.h"
    
    int main(int argc, const char * argv[])
    {
        @autoreleasepool {
            Student *student = [[[Student alloc]init]autorelease];
            [student changeCourseName:@"数学课"];
            NSLog(@"初始值:%@", [student valueForKey:@"courseName"]);
            
            //创建页面实例
            PageView *pageview = [[[PageView alloc]init:student]autorelease];
            
            [student setValue:@"化学课" forKey:@"courseName"];
            [student changeCourseName:@"英语课"];
            NSLog(@"直接改变的课程为:%@", [student valueForKey:@"courseName"]);
    
        }
        return 0;
    }
    复制代码

    直接调用changeCourseName方法改变课程,打印结果:

    2012-07-24 16:32:06.230 objectiveC[2240:403] 初始值:数学课

    2012-07-24 16:32:06.237 objectiveC[2240:403] PageView课程被改变了

    2012-07-24 16:32:06.238 objectiveC[2240:403] PageView新课程是:化学课 老课程是:数学课

    2012-07-24 16:32:06.239 objectiveC[2240:403] 直接改变的课程为:英语课

    可以看到,这时Pageview的回调没被调用到。说明只有通过键值编码(KVC)改变的值,才会回调观察者注册的方法。

    这里是苹果官网的关于KVO的文档,英文好的朋友可以看看:

    https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/KeyValueObserving/KeyValueObserving.html#//apple_ref/doc/uid/10000177-BCICJDHA 

  • 相关阅读:
    D. Babaei and Birthday Cake--- Codeforces Round #343 (Div. 2)
    Vijos P1389婚礼上的小杉
    AIM Tech Round (Div. 2) C. Graph and String
    HDU 5627Clarke and MST
    bzoj 3332 旧试题
    codeforces 842C Ilya And The Tree
    codesforces 671D Roads in Yusland
    Travelling
    codeforces 606C Sorting Railway Cars
    codeforces 651C Watchmen
  • 原文地址:https://www.cnblogs.com/xitang/p/4017741.html
Copyright © 2011-2022 走看看