美文网首页将来跳槽用
KVC使用与实现原理

KVC使用与实现原理

作者: Lxin_ | 来源:发表于2019-04-14 19:20 被阅读9次

    KVC介绍

    KVC是Key Value Coding的简称。它是一种可以通过字符串的名字(对象中属性的名称)(key)来访问类属性的机制,而不是通过调用Setter、Getter方法访问。KVC的方法定义在Foundation/NSKeyValueCoding中。

    KVC用法

    • setValue: forKey:(为对象的属性赋值)
    • setValue: forKeyPath:(为对象的属性赋值(包含了setValue:forKey:的功能,并且还可以对对象内的类的属性进行赋值))
    • valueForKey:(根据key取值)
    • valueForKeyPath:(根据keyPath取值)
    • setValuesForKeysWithDictionary:(对模型进行一次性赋值)

    赋值的使用及实现步骤

    Person.h

    #import <Foundation/Foundation.h>
    
    interface Person : NSObject
    
    @property (nonatomic, copy) NSString *name;
    @property (nonatomic, assign) NSInteger age;
    
    @end
    

    Person.m

    #import "Person.h"
    
    @implementation Person
    
    - (void)setName:(NSString *)name {
        NSLog(@"setName:");
    }
    
    - (void)_setName:(NSString *)name {
        NSLog(@"_setName:");
    }
    
    - (void)setIsName:(NSString *)name {
        NSLog(@"setIsName:");
    }
    
    + (BOOL)accessInstanceVariablesDirectly {
        NSLog(@"accessInstanceVariablesDirectly");
        return YES;
    }
    
    - (void)setValue:(id)value forUndefinedKey:(NSString *)key {
        NSLog(@"setValue: forUndefinedKey:");
    }
    
    - (void)setNilValueForKey:(NSString *)key {
        NSLog(@"setNilValueForKey:");
    }
    
    @end
    

    ViewController.m

    #import "ViewController.h"
    #import "Person.h"
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        Person *person = [[Person alloc] init];
        [person setValue:@"Alex" forKey:@"name"];
    }
    
    @end
    

    当通过注释@property (nonatomic, copy) NSString *name;
    依次注释Person.m文件中各方法,Person.h中添加Person类的成员属性_name、_isName、name、isName

    @interface Person : NSObject {
        NSString *_name;
        NSString *_isName;
        NSString *name;
        NSString *isName;
    }
    

    以及依次注释4个成员属性,得出如下结论。

    1. [person setValue:@"Alex" forKey:@"name"]
    2. 先去找Person类的setName:方法,如果有,通过setName:方法来设置属性
    3. 如果没有setName:方法,再依次找_setName:setIsName:方法设置属性
    4. 如果无上述setter方法,查找+ (BOOL)accessInstanceVariablesDirectly方法(默认已实现,返回Yes),如果为Yes,继续往下执行,否则执行6。
    5. 分别查找成员变量_name_isNamenameisName,如果存在,赋值。
    6. 如果上述都不存在,调用- (void)setValue:(id)value forUndefinedKey:(NSString *)key方法,如果这个方法没有重写,直接崩溃。

    取值的使用及实现步骤

    1. [person valueForKey:@"name"];
    2. 首先按getNamenameisName的顺序查找getter方法,找到直接调用。如果是BOOL、int等内建值类型,会做NSNumber的转换。
    3. 上面的getter没找到,查找countOfKeyobjectInKeyAtindexKeyAtindexes格式的方法。如果countOfKey和另外两个方法中的一个找到,那么就会返回一个可以响应NSArray所有方法的代理集合的NSArray消息方法。
    4. 还没找到,查找countOfKeyenumeratorOfKeymemberOfKey格式的方法。如果这三个方法都找到,那么就返回一个可以响应NSSet所有方法的代理集合。
    5. 还是没找到,如果类方法- (void)setValue:(id)value forUndefinedKey:(NSString *)key返回YES。那么按_key_isKeykeyiskey的顺序搜索成员名。
    6. 再没找到,调用valueForUndefinedKey,如果这个方法没有重写,则直接崩溃。

    相关文章

      网友评论

        本文标题:KVC使用与实现原理

        本文链接:https://www.haomeiwen.com/subject/gziswqtx.html