博客> KVC/KVO常用方法及使用场景
KVC/KVO常用方法及使用场景
2019-04-21 22:22 评论:0 阅读:643 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 回到顶部
GTHFX金钻集团:美贸易战开打 金价V型大逆转 曝尤文开始为布冯选接班人 意甲名将领衔4人候选 新华国际时评:互利共赢,让中美经贸磋商不断向前 民进党为竞选闹“分家”内部掀起“口水战” 美军特种部队遭伏击四人阵亡 战斗全过程视频曝光 4名青年为取乐 多次登门侮辱殴打残疾夫妇 鲁媒:山东将与凯撒商讨续约 欲引入国字号球员 曾带湖人2连冠的中锋 如今被香港2级联赛拒绝 南昌赛中国金花会师女单女双决赛 WTA史上头一遭 台生:台湾人还以为大陆啃树皮 其实进步吓死人 冯远征谈“小鲜肉霸屏”:百姓一直都喜欢有演技的 北京积分落户申报启动 用人单位需配合开展啥工作
外媒:四国加强对南太国家外交 与中国争夺影响力 北京市政交通一卡通充值今起可在线领取电子发票 关税压力让宝洁扛不住了 纸尿裤等产品北美全线涨价 躺着也能赚钱!曼联若拿欧冠伊布将获巨额奖金 盘前:四重魔力日到来 美期指小幅下跌 韩国顶尖大学研究“杀手机器人” 遭多国专家抵制 江西一干部工作时间干“滴滴” 累计接单105次 以太坊创始人“V神”可能加入谷歌 致力于区块链项目 37岁跻身省管干部 3年后他就出事了(图) 权健去年就已敲定U20国青小将 索萨将要对其考察 英媒称中国将用4大武器夺海洋控制权 挑战美国地位 莫迪称要推进武器国产化 并向全世界卖印度武器
“严书记女儿”事件回顾:8日后严春风再无亮相 马斯克成功撩妹的AI梗:是“史上最危险的思想实验” 中甲北控官宣郭维维任俱乐部总经理 杨俊生卸任 环保部向28城市发督办函 问题不及时整改将被问责 全国政协委员尚红:保护青少年免受网约性行为侵害 中美贸易货币政策是筹码?易纲:不干预长期汇率 “月宫365实验”今日出舱 再创世界纪录 日媒:美国计划将核裁军设施改为核武器兵工厂 中超-埃德尔吃饼李昂乌龙 苏宁1-1平10人鲁能 卖什么利润大不压货 投资两万的小型加工厂 如何创业白手起家 90后如何白手起家 AG亚游集团