关闭

KVC和KVO

174人阅读 评论(0) 收藏 举报
分类:

KVC和KVO

1.KVC: key for Coding,KVC,即是指NSKeyValueCoding,一个非正式的Protocol(协议),提供一种机制来间接访问对象的属性,而KVO是基于KVC的.

KVC需要针对属性来说,比如一个类Student,它有属性name,一般来讲,所谓的key只是个字符串,一般比如Student属性name的key,那么就是@”name”,而它对应的值可以是任意类型的对象比如@”name”这个key对应的值(value)可以是个字符串@”Jim”,也可以是一个类,类名叫Name,里面可能还有更多的属性familyName,secondName.这要看你如何来定义这个value,以下为例子

            //先定义一个Dog类的实例变量dog
            Student *Jim = [Student alloc] init];
            //定义一个Name类
            Name *nameForJim = [Name alloc] init];
            name.familyName = @"Wang";
            //使用KVC给Jim的name属性赋值(即把Jim的"name"这个key赋一个value,这个value为nameForJim,是一个Name类,个人理解为就是Jim.name = nameForJim;初学,有错误请纠正
            [Jim setValue:nameForJim forKey:@"name"];
            //获取Jim的name,个人理解为使用一个Name实例来获取Jim的name属性
            Name *nameForJim = [Jim valueForKey:@"name"];
            如果需要在更下一层的使用,则需要使用valueForKeyPath,比如这里需要获取到Jim的familyName的值@"Wang",实现后相当于是NSString *familyNameForJim =Jim.name.familyName:
            NSString *familyNameForJim = [Jim valueForKeyPath:@"name.familyName"];
            也相当于:
            [[Jim valueForKey:@"name"] valuForKey:@"familyName"];

2.KVO:Key -Value Observing,它是建立在KVC的基础之上,能观察到对象的KVC的变化

如上都设置好以后,如果Jim突然有一天改名字了,改叫Tom,这个时候,我们需要做一件事情,那就是把这个消息告诉他的女朋友Lucy,但是可能Lucy可能在很远的地方,这时候我们就可以使用KVO,个人感觉有的点类似通知:

        //先定义下这个Tom的名字nameForTom,这是一个全新的名字,内部我们不管他是姓王还是姓朴,我们要达到的目的是,只要Jim改成这个名字了,就告诉Lucy(Lucy这个名字没有意义,只是说这件事情而已,不要纠结她的构成了...)
        Name *nameForTom = [Name alloc] init];
        [Jim setValue:nameForTom forKey:@"name"];
        //好了,名字改好了,我们该添加观察者了,下面的options是观察的地方的单数设置,可以取new或者old,到时候可以调用字典
        [Jim addObserver:observer
                 forKeyPath:@"age"
                    options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld
        context:[Jim class]];
        //以下代码从别处转载大致改了下,但是这个context还是不太理解,若有看到此处的,请给点指点:
        - (void) observeValueForKeyPath:(NSString *)keyPath
                   ofObject:(id)object 
                     change:(NSDictionary *)change
                    context:(void *)context
    {
        if ([keyPath isEqualToString:@"age"])
        {
            Class classInfo = (Class)context;
            NSString * className = [NSString stringWithCString:object_getClassName(classInfo)
                                                      encoding:NSUTF8StringEncoding];
            NSLog(@" >> class: %@, name changed", className);

            NSLog(@" old name is %@", [change objectForKey:@"old"]);
            NSLog(@" new name is %@", [change objectForKey:@"new"]);
            //然后执行 告诉Lucy他改名字了这样一个方法
            [self tellLucyThatJimHasChangedAName];
        }
        else
        {
            [super observeValueForKeyPath:keyPath
                                 ofObject:object
                                   change:change
                                  context:context];
        }
    }
    个人理解是这样子:keyPath即观察的类的keyPath,比如现在咱们要观察的Jim,他要变动的就是@"name",如果你要观察多个都有这个属性的类,那么需要判断是谁(参数object)的这个@"name".context看着像是类型,这里没有太理解,然后change参数对应传过来的是比如old即改变之前的值,和new改变之后的值,需要用到哪些值,在之前加入观察者的时候的option模式中设置,一般设置为new和old.
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:10195次
    • 积分:317
    • 等级:
    • 排名:千里之外
    • 原创:22篇
    • 转载:4篇
    • 译文:0篇
    • 评论:1条
    文章分类
    最新评论
  • AppCode的使用

    sinat_37342382: TODO功能里面包含TODO和FIXME就是方便你工作做一半发现做不下去,留个记号。比如你现在正在开...