zoukankan      html  css  js  c++  java
  • KVC(键值编码)(二十五)

    kvc的英文全称是key-value-coding,意思就是键值对编码。用普通的话来说,就是kvc就是通过使用键(字符串)来取值的一种编码。是一种间接访问对象属性的机制,不需要调用getter、setter这些存取方法,就可以直接访问对象属性。

    我们声明的变量,有可见度。有些私有的,或者受保护的变量,在其他类中,不能直接使用。我们可以通过kvc,用对象在类外部对实例变量进行访问和赋值。不论是什么可见度的实例变量(private,protected,public)。

    setValue: forKey:

    setValue:@”1111” forKey:@”name”。以此来举例说明,我们的key为name,此时,对象在调用这个方法的时候,会去找我们的声明中,有没有这个name对应的变量或者属性(名字必须是name或者_name)。否则会导致程序找不到匹配的变量,崩溃。

    这个方法,优先调用setter方法,即setXxx这种格式的方法,这个set后的Xxx转换成小写后,就可以作为这个key。

    如果这时候,找不到匹配的setter方法,就会去找实例变量,并且自动匹配下划线 _ 。(我们在key中加不加下划线 _ 都可以)。如果两者都找不到,就会崩溃。

    Person.h

    #import <Foundation/Foundation.h>

    @interface Person : NSObject{

        @private

        NSString *_name;

       

        NSString *_sex;

    }

     

    - (void)sayHi;

    @end

    Person.m

    #import "Person.h"

     

    @implementation Person

    - (void)sayHi{

        NSLog(@"%@",_name);

    }

    @end

    main.m

    #import <Foundation/Foundation.h>

    #import "Person.h"

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

        @autoreleasepool {

            Person *p1 = [[Person alloc]init];   

     //setValue:forKey:

            //优先调用setter方法,即:setXxx:,这个set后面的 Xxx 就可以作为key。

            //其次,set方法没有找到,就去找实例变量。并且自动识别下划线。(我们在key里加不加下划线都可以识别名字)。如果名字不一样,崩溃

            p1->_name;

            //kvc第一个方法:

            [p1 setValue:@"123" forKey:@"name"];

            NSLog(@"%@",[p1 valueForKey:@"name"]);

        }

        return 0;

    }

    解释:

    [p1 setValue:@"123" forKey:@"name"];p1在设置key为name的变量的值为“123”,此时就回去找setter方法,发现没有定义setter方法,就回去实例变量中匹配,发现有一个_name,与之匹配,则对 _name进行赋值。

    valueForKey:用键取值

    通过键来取value,优先调用getter方法,取值,即形如我们定义的getter方法的方法xxx,((返回值)方法名,这样的方法就是形如getter方法。方法名就作为key),如实没有找到getter方法,就会去找实例变量,并能识别下划线 _。

    NSLog(@"%@",[p1 valueForKey:@"name"]);

    解释:去找name的getter方法,发现没找到,就去找实例变量,匹配到了,就可以取到值。

    valueForKey:不仅可以取到变量值,还能用方法名作为key去找一个方法,然后执行。

    Person.h

    #import <Foundation/Foundation.h>

     

    @interface Person : NSObject{

        @private

        NSString *_name;

       

        NSString *_sex;

    }

    - (void)sayHi;

    @end

    Person.m

    #import "Person.h"

    @implementation Person

    - (void)sayHi{

        NSLog(@"%@",_name);

    }

     

    - (void)setLol:(NSString *)lol{

        NSLog(@"%@",lol);

    }

    //没有找到对应key

    - (void)setValue:(id)value forUndefinedKey:(NSString *)key{

        NSLog(@"没有key:%@,value:%@",key,value);

    }

    - (id)valueForUndefinedKey:(NSString *)key{

        NSLog(@"没有 key :%@",key);

        return nil;

    }

    @end

    main.m

            [p1 sayHi];

            [p1 valueForKey:@"sayHi"];

           

            [p1 setValue:@"德玛西亚" forKey:@"Lol"];//2015-04-22 16:08:00.048 OClesson8_KVC[2113:121073] 德玛西亚

    解释:

    在.h中声明了sayHi方法,在.m中实现sayHi,此时在main函数中用p1对象调用valueForKey:@"sayHi",就会把这个sayHi字符串去匹配,发现匹配了一个方法,此时就会去调用这个方法,执行。

    在.m中实现了Lol:这个方法,在main方法中,对象p1调用了setValue:@"德玛西亚" forKey:@"Lol"方法,就把Lol作为key去匹配,发现匹配了setLol:方法,此时就会把value当作参数传进去,执行setLol:方法。

    从父类继承过来的私有,受保护的实例变量,也可以用kvc访问。

    setValue: forKeyPath:按照路径设置值

    valueForKeyPath: 按照路径取值

    若实例变量中有我们自定义的类,这个自定义的类中有另外的实例变量。此时要想访问实例变量为自定义类中的实例变量,就需要kvc按路径访问。

    setValue:forUndefinedKey:设置值匹配不到key的处理

    valueForUndefinedKey: 取值匹配不到key的处理

    如果在按key访问变量或方法的时候,匹配不到所给的字符串(也就是key),需要加上setValue:forUndefinedKey(设置值)或者valueForUndefinedKey(取值)进行相应的处理,防止程序崩掉。

    setValuesForKeysWithDictionary:按字典设置值

    当有很多个值得时候,我们可以一次性赋值,就是用字典来赋值。

    Person.h(父类)

    #import <Foundation/Foundation.h>

     

    @interface Person : NSObject{

        @private

        NSString *_name;

       

        NSString *_sex;

    }

    - (void)sayHi;

    @end

    Person.m(父类实现)

    #import "Person.h"

    @implementation Person

    - (void)sayHi{

        NSLog(@"%@",_name);

    }

    - (void)setLol:(NSString *)lol{

        NSLog(@"%@",lol);

    }

    //没有找到对应key

    - (void)setValue:(id)value forUndefinedKey:(NSString *)key{

        NSLog(@"没有key:%@,value:%@",key,value);

    }

    - (id)valueForUndefinedKey:(NSString *)key{

        NSLog(@"没有 key :%@",key);

        return nil;

    }

     

    @end

    Student.h(继承于Person类)

    #import "Person.h"

    @class Book;

    @interface Student : Person{

        Book *_book;

    }

    @end

    Student.m

    #import "Student.h"

    #import "Book.h"

    @implementation Student

     

    @end

    Book.h(继承于Student类)

    #import <Foundation/Foundation.h>

    @interface Book : NSObject{

        NSString *_bookName;

    }

    @end

    Book.m

    #import "Book.h"

     

    @implementation Book

     

    @end

    main.m

    #import <Foundation/Foundation.h>

    #import "Person.h"

    #import "Student.h"

    #import "Book.h"

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

        @autoreleasepool {

            Person *p1 = [[Person alloc]init];

           

            Student *s1 = [[Student alloc]init];

            //从父类继承的私有实例变量,也可以用kvc访问。

            [s1 setValue:@"22222" forKey:@"name"];

           

            NSLog(@"%@",[s1 valueForKey:@"name"]);//2015-04-22 16:21:33.162 OClesson8_KVC[2186:125614] 22222

          

            Student *s2 = [[Student alloc]init];

            Book *b1 = [[Book alloc]init];

    //        [b1 setValue:@"红楼梦" forKey:@"bookName"];

            [s2 setValue:b1 forKey:@"book"];

            [s2 setValue:@"红楼梦" forKeyPath:@"book.bookName"];//点 . 不是点语法,是路径的意思。

           

            NSLog(@"%@",[s2 valueForKeyPath:@"book.bookName"]);//2015-04-22 16:32:49.975 OClesson8_KVC[2236:129639] 红楼梦

           

    //      //设置值没有对应的key,在person.m中写一个undifind 

    //    [p1 setValue:@"12131313" forKeyPath:@"num"];//2015-04-22 16:54:24.955 OClesson8_KVC[2324:135915] 没有key:num,value:12131313

    //        //取值没有对应的key,在person.m中写一个undifind

    //        [p1 valueForKeyPath:@"num"];//2015-04-22 16:56:22.108 OClesson8_KVC[2348:136844] 没有 key :num

           

            NSDictionary *dict = @{@"name":@"Mick",@"sex":@"男"};

            //一次性赋多个值,在网络解析中常用。

            [p1 setValuesForKeysWithDictionary:dict];

        }

        return 0;

    }

  • 相关阅读:
    linux 之文网络编程基础 (二)、大小端、地址地址转换函数
    linux 之文网络编程基础 (一)、网络编程基本概念
    Linux下静态库与动态库简单制作与使用
    linux 之文件基础 (五)、文件属性
    C++ pair
    Ice 线程与并发 C++
    linux 之文件基础 (四)、标准IO的API
    linux 之文件基础 (三)、标准IO的两个概念:流、缓冲区
    linux 之文件基础 (二)、文件IO API
    linux 之线程基础 (三)、多线程编程的同步和互斥
  • 原文地址:https://www.cnblogs.com/DevinSMR/p/5118638.html
Copyright © 2011-2022 走看看