美文网首页
八:KVC底层原理探究(下)

八:KVC底层原理探究(下)

作者: Mr姜饼 | 来源:发表于2021-01-06 16:06 被阅读0次

前言:

上小节为大家介绍了kvc设值的流程,这节为大家继续讲解一下kvc取值的流程,其实流程和设值的方式差不多,大家可以按照上节课的代码测试流程来进行验证,这里就不为大家多做介绍了。

测试代码:

@interface JPerson : NSObject

@end

@implementation JPerson
{
    NSString* name;
    NSString* isName;
    NSString* _name;
    NSString* _isName;
}


- (id)init{
    if(self = [super init])
    {
        name = @"1";
        isName = @"2";
        _name = @"3";
        _isName = @"4";
    }
    return self;
}

- (id)getName{
    return @"getName";
}

- (id)name{
    return @"name";
}

- (id)_name{
    return @"_name";
}

- (id)isName{
    return @"isName";
}

+ (BOOL)accessInstanceVariablesDirectly{
    return YES;
}

- (void)setValue:(id)value forUndefinedKey:(NSString *)key{
    NSLog(@"%@‘s key is not founded --%s--",key,__func__);
}

- (id)valueForUndefinedKey:(NSString *)key{
    NSLog(@"%@‘s value is not founded --%s--",key,__func__);
    return [NSNull null];
}
@end

@interface JTestVC ()

@end

@implementation JTestVC

- (void)viewDidLoad {
    [super viewDidLoad];
    JPerson *person = [JPerson new];
    
    NSString* value = [person valueForKey:@"name"];
    
    NSLog(@"value = %@",value);
    
}

大家可以一次次地注释某段代码,来验证每一步的顺序。

得出结论:

image.png

扩展:

setValue:forKeyPath: 
valueForKeyPath:

看以下的例子:

@interface Wallet : NSObject
@property(nonatomic , assign)int dollars;
@end

@implementation Wallet
@end

@interface Person : NSObject
@property(nonatomic , strong)Wallet* wallet;

@end

@implementation Person
- (id)init{
    if(self = [super init]){
        _wallet = [[Wallet alloc] init];
    }
    return self;
}


@end


@interface JTest2ViewController ()

@end

@implementation JTest2ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    
    Person* xiaoming = [Person new];
    [xiaoming setValue:@100 forKeyPath:@"wallet.dollars"];
    
    
    NSNumber* dollars = (id)[xiaoming valueForKeyPath:@"wallet.dollars"];
    NSLog(@"have %d dollars",[dollars intValue]);
    
    // Do any additional setup after loading the view.
}

输出语句:

2021-01-06 15:56:37.028829+0800 TestDemo[21131:222598] have 100 dollars

是不是超级好用呀~~~~~~,跨路由的方式进行设置和取值

KVC 使用场景:

1、动态设值和取值

  • 常用的可以通过setValue:forKey:valueForKey:

  • 也可以通过路由的方式setValue:forKeyPath:valueForKeyPath:

2、通过KVC访问和修改私有变量

在日常开发中,对于类的私有属性,在外部定义的对象,是无法直接访问私有属性的,但是对于KVC而言,一个对象没有自己的隐私,所以可以通过KVC修改和访问任何私有属性

3、多值操作(model和字典互转)

参考YYModel

4、修改一些系统空间的内部属性

在日常开发中,我们知道,很多UI控件都是在其内部由多个UI空间组合而成,这些内部控件苹果并没有提供访问的API,但是使用KVC可以解决这个问题,常用的就是自定义tabbar、个性化UITextField中的placeHolderText

5.使用集合操作符取值

NSArray *score = @[@(89),@(80),@(20),@(56),@(89),@(100),@(89),@(89)];
NSLog(@"%@",[score valueForKeyPath:@"@count.self"]);//8
NSLog(@"%@",[score valueForKeyPath:@"@sum.self"]);//612
NSLog(@"%@",[score valueForKeyPath:@"@max.self"]);//100
NSLog(@"%@",[score valueForKeyPath:@"@min.self"]);//20
NSLog(@"%@",[score valueForKeyPath:@"@avg.self"]);//76.5
Person *person1 = [[Person alloc] init];
person1.name = @"王五";
person1.age = 10;
person1.position = @"学生";

Person *person2 = [[Person alloc] init];
person2.name = @"赵六";
person2.age = 19;
person2.position = @"学生";

Person *person3 = [[Person alloc] init];
person3.name = @"张三";
person3.age = 30;
person3.position = @"公司高管";

Person *person4 = [[Person alloc] init];
person4.name = @"李四";
person4.age = 25;
person4.position = @"软件开发";

Person *person5 = [[Person alloc] init];
person5.name = @"七七";
person5.age = 19;
person5.position = @"学生";

NSArray *personArr = @[person1,person2,person3,person4,person5];
NSLog(@"%@",[personArr valueForKeyPath:@"@distinctUnionOfObjects.age"]);
#输出结果为:10, 30,  19, 25(去重)
NSLog(@"%@",[personArr valueForKeyPath:@"@unionOfObjects.age"]);
#输出结果为:10, 19, 30,25, 19(没有去重)

相关文章

网友评论

      本文标题:八:KVC底层原理探究(下)

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