当前位置:编程学习 > C/C++ >>

Objective-C语法之KVO的使用

简介:
上篇我们讲到了KVC,这篇我们学习KVO,全名为:Key Value Observing,直译为:基于键值的观察者。
那它有什么用呢?KVO主要用于视图交互方面,比如界面的某些数据变化了,界面的显示也跟着需要变化,那就要建立数据和界面的关联。
ObjC中提供的KVO就是解决这种问题的。以下用显示页面观察学生的课程名称变化的例子来说明KVO的使用。
学生类命名为:Student,页面类是:PageView.

上图来自苹果官网,图中的BankObject好比PageView,PersonObject好比Student,
PageView观察Student的变化。
1、添加Student学生类。
.h
[cpp] 
#import <Foundation/Foundation.h> 
@inte易做图ce Student : NSObject 

    NSString *name; 
    NSString *courseName; 

-(void)changeCourseName:(NSString*) newCourseName; 
@end 
类中有name,和课程名称courseName,添加一个可以改变课程名称的方法changeCourseName。一会用来做对比,看直接改变课程名称时会不会有回调。
实现文件.m
[cpp] 
#import "Student.h" 
 
@implementation Student 
-(void)changeCourseName:(NSString*) newCourseName 

    courseName = newCourseName; 

@end 
实现类把方法实现了。
2、页面类实现
.h文件
[cpp] 
#import <Foundation/Foundation.h> 
@class Student; 
@inte易做图ce PageView : NSObject 

    Student *student; 

-(id)init:(Student*)initStudent; 
@end 
.m文件
[cpp] 
#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函数中
[cpp] 
#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、直接改变课程信息对比
[cpp]
#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; 


作者:totogo2010
补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,