博客> KVC/KVO常用方法及使用场景
KVC/KVO常用方法及使用场景
1小时前 评论:0 阅读:76 aa100056
ios kvo kvc

1. KVC常用方法:

1.1 赋值方法:

  • -(void)setValue:(nullable id)value forKey:(NSString *)key;
  • -(void)setValue:(nullable id)value forKeyPath:(NSString *)keyPath;
  • -(void)setValue:(nullable id)value forUndefinedKey:(NSString *)key;
  • -(void)setValuesForKeysWithDictionary:(NSDictionary *)keyedValues;

1.2 取值方法:

/能取得私有成员变量的值

  • -(id)valueForKey:(NSString *)key;
  • -(id)valueForKeyPath:(NSString *)keyPath;
  • -(id)valueForUndefinedKey:(NSString *)key;

2. KVC使用场景

Person person = [[Person alloc] init]; /name、dog、sex1为person的成员变量,kind为dog的成员变量 Dog dog = [[Dog alloc] init]; 1)setValue: forKey: 方法 [person setValue:@"张三" forKey:@"name"]; 2)setValue: forKeyPath: 方法 [person setValue:dog forKeyPath:@"dog.kind"]; 3)setValue: forUndefinedKey: 方法 当[person setValue:@"男性" forKey:@"sex1"];由于person没有sex1成员变量,只有sex成员变量,会报错; 因此需要在person类重写setValue: forUndefinedKey: 方法: -(void)setValue:(id)value forUndefinedKey:(NSString )key{ if ([key isEqualToString:@"sex1"]) { /将sex1的值赋值给_sex,或者不设值,即可避免报错 sex = value;}} 4) setValuesForKeysWithDictionary: 方法 /字典快速转化成模型 NSDictionary dic = @{@"name":@"张三",@"sex":@"男",@"age":@"22"}; [person setValuesForKeysWithDictionary:dic]; 注:当dic中存在模型没有的字段或者不同字段名时,会报运行时错误;可以通过重写setValue: forUndefinedKey: 方法,过滤不存在的键值对或重新赋值。 5) valueForKey: 方法 [person valueForKey:@"name"]; 6) valueForKeyPath: 方法 [person valueForKeyPath:@"dog.kind"] 7) valueForUndefinedKey:方法 /当取值的时候, 找不到相应的key, 会调用该方法 -(id)valueForUndefinedKey:(NSString *)key{ if ([key isEqualToString:@"sex1"]) { return _sex; }}

3. KVO实现步骤

*注册

/keyPath就是要观察的属性值 /options给你观察键值变化的选择 NSKeyValueObservingOptions: NSKeyValueObservingOptionNew 新值 NSKeyValueObservingOptionOld 旧值 NSKeyValueObservingOptionInitial 注册后立刻触发KVO通知 NSKeyValueObservingOptionPrior 2次回调,变化前后 /context上下文,这个会传递到订阅着的函数中,用来区分消息,所以应当是不同的 -(void)addObserver:(NSObject )anObserver forKeyPath:(NSString )keyPath options: (NSKeyValueObservingOptions)options context:(void *)context

*实现方法

/change里存储了一些变化的数据,比如变化前的数据,变化后的数据;如果注册时context不为空,这里context就能接收到。 -(void)observeValueForKeyPath:(NSString )keyPath ofObject:(id)object change:(NSDictionary )change context:(void *)context;

*移除

-(void)removeObserver:(NSObject )observer forKeyPath:(NSString )keyPath;

KVO注意事项

KVO的addObserver和removeObserver需要是成对的,如果重复remove则会导致NSRangeException类型的Crash,如果忘记remove则会在观察者释放后再次接收到KVO回调时Crash。 苹果官方推荐的方式是,在init的时候进行addObserver,在dealloc时removeObserver,这样可以保证add和remove是成对出现的,是一种比较理想的使用方式。

手动调用KVO

如果一个类(这个类指key所在的类)想要实现手动的change notification发送,则必须重写NSObject实现的automaticallyNotifiesObserversForKey:方法,并对需要实现手动发送的key返回NO,其余则调用super。 +(BOOL)automaticallyNotifiesObserversForKey:(NSString *)theKey { BOOL automatic = NO; if ([theKey isEqualToString:@"age"]) { automatic = NO; } else { automatic = [super automaticallyNotifiesObserversForKey:theKey]; } return automatic; } 然后在property的值改变之前调用willChangeValueForKey:,在值改变之后调用didChangeValueForKey:。当然,在什么样的情况下才调用这两个方法,是由第三方程序的逻辑决定的。 如果一个操作造成了多个key的值的改变,则willChangeValueForKey:和didChangeValueForKey:必须嵌套着调用。 -(void)setAge:(NSInteger)age{ if (age != _age) { [self willChangeValueForKey:@"age"]; _age = age;/第三方程序的逻辑处理 [self didChangeValueForKey:@"age"]; } }

收藏
1
sina weixin mail AG亚游集团回到顶部
毒贩持刀拒捕挟持出租车 警察开枪将其击伤终擒获 日本官方解释前后矛盾 陆基宙斯盾部署迷失方向 好莱坞六大变五家 迪士尼713亿美元收购福克斯获批 十三届全国人大一次会议5日上午9时开幕 美股何时会再次大跌?投资者从比特币寻找线索 美联储主席说继续渐进加息有望推动充分就业 中美经贸磋商取得共识 全球市场普涨 棕榈油谨慎看多 哪些领导干部涉赌腐败和充当“保护伞”被通报 印度女子生两个女孩 妇女节遭丈夫泼浓酸面目全非 VAR决定赛果开创中超先河 降低误判却成为双刃剑 特朗普批评油价被“人为”抬高 遭OPEC否认反驳
广东珠海市政协原主席钱芳莉因受贿一审获刑13年 姚明寄语2018准新秀:为CBA变得更好而一起努力 国际锐评:中国将是外国投资者不可失去的财富市场 非农结果令美股如释重负 而FED加息预期仍分歧较大 上海媒体赞秦升德比战控制了情绪 还曾扮演和事佬 胡煜清回应:觉得就像看了部大片 不做评论 父陷丑闻远亲“杀人魔” 英准王妃亲戚让人不省心 金基独立玩出花! 两球看西决41分是怎么赢的 韩国媒体狂吹全北空霸戴帽:状态超好如天神附体 韩国2017年军备出口猛增25% 成为世界军火市场新秀 王小川委员提案:科研资金向有科研和转化实企业倾斜 何为职场性骚扰? 联合国要定国际标准了
Facebook大幅提高内容审查团队预算以清扫仇恨言论 海澜之家入驻美团:高额存货处理引关注 鲁媒:CBA公司调查避重就轻 计时员是否有猫腻? 大学生带家乡特产返校 室友:流着泪也要吃下去 火箭赢了一场球后,整个西部都被搅乱了! 中方:中美关系处在十字路口 望美不要逆潮流而动 俄铝迎来喘息之机 欧柏嘉放弃对En+控制权 WTA最新排名:王蔷逼近TOP50 01后新星飙升75… 毅力惊人! 残疾女子带轮椅做引体向上 养一百只土鸡利润多少 现在什么行业挣钱快 笨蛋也能年赚100万txt 地摊卖什么最火 AG亚游集团