- (nullable id)valueForKey:(NSString *)key;

1 篇文章 0 订阅

取值

当调用valueForKey:@”name“的代码时,KVC对key的搜索方式不同于setValue:属性值 forKey:@”name“,其搜索方式如下:

  • 首先按get<Key>,<key>,is<Key>的顺序方法查找getter方法,找到的话会直接调用。如果是BOOL或者Int等值类型, 会将其包装成一个NSNumber对象。
  • 如果上面的getter没有找到,KVC则会查找countOf<Key>,objectIn<Key>AtIndex<Key>AtIndexes格式的方法。如果countOf<Key>方法和另外两个方法中的一个被找到,那么就会返回一个可以响应NSArray所有方法的代理集合(它是NSKeyValueArray,是NSArray的子类),调用这个代理集合的方法,或者说给这个代理集合发送属于NSArray的方法,就会以countOf<Key>,objectIn<Key>AtIndex<Key>AtIndexes这几个方法组合的形式调用。还有一个可选的get<Key>:range:方法。所以你想重新定义KVC的一些功能,你可以添加这些方法,需要注意的是你的方法名要符合KVC的标准命名方法,包括方法签名。
  • 如果上面的方法没有找到,那么会同时查找countOf<Key>enumeratorOf<Key>,memberOf<Key>格式的方法。如果这三个方法都找到,那么就返回一个可以响应NSSet所的方法的代理集合,和上面一样,给这个代理集合发NSSet的消息,就会以countOf<Key>enumeratorOf<Key>,memberOf<Key>组合的形式调用。
如果还没有找到,再检查类方法 + (BOOL)accessInstanceVariablesDirectly,如果返回YES(默认行为),那么和先前的设值一样,会按 _<key>,_is<Key>,<key>,is<Key>的顺序搜索成员变量名,这里不推荐这么做,因为这样直接访问实例变量破坏了封装性,使代码更脆弱。如果重写了类方法 + (BOOL)accessInstanceVariablesDirectly返回NO的话,那么会直接调用 valueForUndefinedKey:还没有找到的话,调用 valueForUndefinedKey:


如果还没有找到,再检查类方法 + (BOOL)accessInstanceVariablesDirectly,如果返回YES(默认行为),那么和先前的设值一样,会按 _<key>,_is<Key>,<key>,is<Key>的顺序搜索成员变量名,这里不推荐这么做,因为这样直接访问实例变量破坏了封装性,使代码更脆弱。如果重写了类方法 + (BOOL)accessInstanceVariablesDirectly返回NO的话,那么会直接调用 valueForUndefinedKey:还没有找到的话,调用 valueForUndefinedKey:

#import <Foundation/Foundation.h>

@interface ObtainValueClass : NSObject

@property (nonatomic,readwrite,assign) NSUInteger count;
@property (nonatomic,copy) NSString* arrName;
-(void)incrementCount;
-(NSUInteger)countOfNumbers;
-(id)objectInNumbersAtIndex:(NSUInteger)index;
@end

#import "ObtainValueClass.h"

@implementation ObtainValueClass


-(void)incrementCount{
    
    NSLog(@"%@", NSStringFromSelector(_cmd));
//    NSLog(@"%lu", (unsigned long)self.count);
    self.count ++;
}
-(NSUInteger)countOfNumbers{
    
    NSLog(@"%@", NSStringFromSelector(_cmd));
    return self.count;
}

-(id)objectInNumbersAtIndex:(NSUInteger)index{     //当key使用numbers时,KVC会找到这两个方法。
    
    NSLog(@"%@", NSStringFromSelector(_cmd));
    return @(index * 2);
    
}

-(NSInteger)getNum{                 //第一个,自己一个一个注释试
    
    NSLog(@"%@", NSStringFromSelector(_cmd));
    return 10;
}

-(NSInteger)num{                       //第二个
    
    NSLog(@"%@", NSStringFromSelector(_cmd));
    return 11;
}

-(NSInteger)isNum{                    //第三个
    
    NSLog(@"%@", NSStringFromSelector(_cmd));
    return 12;
}
@end

 //问题三
    //KVC valueForKey:对 key的搜索机制
    
    //首先按get<Key>,<key>,is<Key>的顺序方法查找getter方法,找到的话会直接调用。如果是BOOL或者Int等值类型, 会将其包装成一个NSNumber对象。
    ObtainValueClass * obj = [[ObtainValueClass alloc] init];
    NSNumber * num  = [obj valueForKey:@"num"];
    NSLog(@"%@",num);

    //如果上面的getter没有找到,KVC则会查找countOf<Key>,objectIn<Key>AtIndex或<Key>AtIndexes格式的方法。如果countOf<Key>方法和另外两个方法中的一个被找到,那么就会返回一个可以响应NSArray所有方法的代理集合(它是NSKeyValueArray,是NSArray的子类),调用这个代理集合的方法,或者说给这个代理集合发送属于NSArray的方法,就会以countOf<Key>,objectIn<Key>AtIndex或<Key>AtIndexes这几个方法组合的形式调用。还有一个可选的get<Key>:range:方法。所以你想重新定义KVC的一些功能,你可以添加这些方法,需要注意的是你的方法名要符合KVC的标准命名方法,包括方法签名。
    
    id numbers = [obj valueForKey:@"numbers"];
    NSLog(@"%@",NSStringFromClass([numbers class]));//简单来说就是如果你在自己的类自定义了KVC的实现,并且实现了上面的方法,那么恭喜你,你可以将返回的对象当数组(NSArray)用了

    NSLog(@"0:%@     1:%@     2:%@     3:%@",numbers[0],numbers[1],numbers[2],numbers[3]);
    
    [obj incrementCount];                                                                            //count加1
    NSLog(@"%lu",(unsigned long)[numbers count]);
    [obj incrementCount];                                                                            //count再加1
    NSLog(@"%lu",(unsigned long)[numbers count]);                                                         //打印出2
    
    [obj setValue:@"newName" forKey:@"arrName"];
    NSString* name = [obj valueForKey:@"arrName"];
    NSLog(@"%@",name);
    



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值