将来跳槽用

KVC使用与实现原理

2019-04-14  本文已影响9人  Lxin_

KVC介绍

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

KVC用法

赋值的使用及实现步骤

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,如果这个方法没有重写,则直接崩溃。
上一篇下一篇

猜你喜欢

热点阅读