仓酷云

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 3151|回复: 19
打印 上一主题 下一主题

[学习教程] IOS编程:iOS KVC & KVO仓酷云

[复制链接]
山那边是海 该用户已被删除
跳转到指定楼层
楼主
发表于 2015-1-18 11:35:07 | 显示全部楼层 回帖奖励 |倒序浏览 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
用代码控制view意思他们玩的都是高科技IB都是垃圾很多人也纠结到底用不用IB的确很多时候IB灵活度不行但是不需要灵活度的时候还不用IB那不是装X吗要是没人用苹果还开发IB干嘛早去掉了IB在很多时候节省很多工作量UINavigationController再说说NavigationController刚接触开发的时候不明白View和View之间怎么切换的KeyValueCoding

KeyValueCoding是cocoa的一个尺度构成部分,它能让我们能够经由过程name(key)的体例会见property,不用挪用明白的propertyacCSSor,如我们有个property叫做foo,我们能够foo间接会见它,一样我们也能够用KVC来完成[ObjectvalueForKey:@“foo”],有同砚就会问了,如许做有甚么优点呢?次要的优点就是来削减我们的代码量。
上面我们来看看几个例子,就分明了KVO的用法亲睦处了,假定如许个类叫做People,
  1. 123456
复制代码
  1. @interfacePeople:NSObject@property(nonatomic,strong)NSString*name;@property(nonatomic,strong)NSNumber*age;@end
复制代码


场景1,apple官网的一个例子,当我们必要统计良多People的时分,每行是一团体的实例,而且有2列属性,name,age,这时候候我们能够会如许做,
  1. 123456789101112
复制代码
  1. -(id)tableView:(NSTableView*)tableviewobjectValueForTableColumn:(id)columnrow:(NSInteger)row{People*people=[peoleArrayobjectAtIndex:row];if([[columnidentifier]isEqualToString:@"name"]){return[peoplename];}if([[columnidentifier]isEqualToString:@"age"]){return[peopleage];}//Andsoon.}
复制代码


一样我们也能够用KVC,匡助我们化简这些if,由于name,age实在都是property,我们能够间接经由过程key来会见,以是收拾事后是
  1. 12
复制代码
  1. People*people=[peopleArrayobjectAtIndex:row];return[peoplevalueForKey:[columnidentifier]];
复制代码


场景2,这下我们有了server,server的某个api(listPeople??),会前往我们json格局一个数组,内里包括如许dict{name:xx,age:xx}如许的数据,我们但愿用这些dict数据机关出我们的people来,一般我们的做法是,为我们People类写一个staticfactory办法专门用来处置dict来,把dict内里的数据掏出来,然后创立个空的People对象,然后顺次设置property。但是当如许相似People的与server交互的类多了,我们就要为每一个类都要加上如许的wrapper,是不是有种复杂举措来设置如许的属性,固然就是我们的KVC了。
  1. 123456789
复制代码
  1. -(id)initWithDictionary:(NSMutableDictionary*)jsonObject{if((self=[superinit])){[selfinit];[selfsetValuesForKeysWithDictionary:jsonObject];}returnself;}
复制代码


setValuesForKeysWithDictionary,会为我们把和dictionary的key名字不异的classproerty设置上dict中key对应的value,是否是很便利呀,可是有同砚又要问了假如json内里的某些key就是和object的property名字纷歧样呢,大概有些server前往的字段是objc保存字如”id”,“description”等,我们也但愿也mapdicttoobject,这时候候我们就必要用上setValue:forUndefinedKey,由于假如我们不处置这些UndefinedKey,仍是用setValuesForKeysWithDictionary就会抛出非常。
  1. 123456789
复制代码
  1. -(void)setValue:(id)valueforUndefinedKey:(NSString*)key{if([keyisEqualToString:@"nameXXX"])self.name=value;if([keyisEqualToString:@"ageXXX"])self.age=value;else[supersetValue:valueforKey:key];}
复制代码


以是只需重载这个办法,就能够处置了那些没法跟property相婚配的key了,默许的完成是抛出一个NSUndefinedKeyException,又有同砚提问了假如这时候候server前往的People有了内嵌的json(如Products{product1{count:xx,sumPrice:xx}},product2{}….),又该怎样办,能把这个内嵌的json转化成我们的客户真个Product类嘛,固然能够这时候候就必要重载setValue:forKey,独自处置”Products”这个key,把它wrapper成我们必要的class
  1. @interfacePeople:NSObject@property(nonatomic,strong)NSString*name;@property(nonatomic,strong)NSNumber*age;@end0
复制代码
  1. @interfacePeople:NSObject@property(nonatomic,strong)NSString*name;@property(nonatomic,strong)NSNumber*age;@end1
复制代码


场景3,我们必要把一个数组里的People的名字的首字母年夜写,而且把新的名字存进新的数组,这时候候一般做法会是遍历全部数组,然后把每一个People的name掏出来,挪用capitalizedString然后把新的String到场新的数组中。有了KVC就有了新做法:
  1. @interfacePeople:NSObject@property(nonatomic,strong)NSString*name;@property(nonatomic,strong)NSNumber*age;@end2
复制代码
  1. @interfacePeople:NSObject@property(nonatomic,strong)NSString*name;@property(nonatomic,strong)NSNumber*age;@end3
复制代码


我们看到valueForKeyPath,为何用valueForKeyPath,不必valueForKey,由于valueForKeyPath能够传送干系,比方这里是每一个People的nameproperty的String的capitalizedStringproperty,而valueForKey不克不及传送如许的干系,以是关于dict内里的dict,我们也只能用valueForKeyPath。这里我们也看到KVC关于array(set),做了特别处置,不是复杂操纵collection上,而是针对这些collection内里的元素举行操纵,一样KVC也供应更多地操纵,比方@sum这些针对collection,有乐趣的同砚能够往用下。
场景4,当我们实行NSArray*products=[peoplevalueForKey:@“products”],我们但愿的是[peopleproducts],但是people没有如许的办法,KVC又会为我们带来些甚么呢?

  • 起首会往找getProdcutsorproductsorisProducts,依照如许的按次往查找,第一个找到的就前往
  • 然后会往找countOfProductsandeitherobjectInProductsAtIndex:orProductsAtIndexes,假如找到,就会往找countOfProductsandenumeratorOfProductsandmemberOfProducts这个2个办法都找到了,KVC才会给我们前往一个代办署理的NSKeyValueArray,用于我们后续的操纵(addProduct之类的)。
  • 假如有个变量叫做products,isProducts,productsorisProducts,KVC会间接就利用如许的变量,假如你以为间接用如许的变量是损坏了封装,能够克制如许的举动产生,重载+accessInstanceVariablesDirectly,前往NO。
复杂来讲,valueForKey,会给我们带来一个代办署理array,假如我们完成了某些办法,上诉的这些办法只是针对NSArray,关于mutable的collection,我们还必要供应其他办法的完成才行。
KeyValueObserving

KeyValueObserving,望文生义就是一种observer形式用于监听property的变更,KVO跟NSNotification有良多类似的中央,用addObserver:forKeyPath:options:context:往startobserver,用removeObserver:forKeyPath:context往stopobserver,回调就是observeValueForKeyPath:ofObject:change:context:。
  1. @interfacePeople:NSObject@property(nonatomic,strong)NSString*name;@property(nonatomic,strong)NSNumber*age;@end4
复制代码
  1. @interfacePeople:NSObject@property(nonatomic,strong)NSString*name;@property(nonatomic,strong)NSNumber*age;@end5
复制代码


关于KVO来讲,我们要做的只是复杂update我们的property数据,不必要像NSNotificationCenter那样体贴是不是有人在监听你的哀求,假如没有人监听该怎样办,一切addObserver,removeObserver,callback都是想要监听的你的property的class做的事变。已经做个项目,用NSNotificationCenterpostNotification在一个networkcallback内里,但是这时候候由于最早的addObserver的class被开释了,接着天生的addObserver的class,就承受到了上一个observer该监听的事务,以是形成了毛病,当时候的办理计划是为addObservekey做unique,不会2次addObserver的key是不异的,可是有了KVO,我们一样能够用KVO来完成,当addOberver的的objectremove的时分,就不会有如许的callback被挪用了。

照着书上的例子,一个一个做下来,只要不是文盲,就都会的呀,没有体现我的一点点个人价值。所以我决定了,不能再这样下去
山那边是海 该用户已被删除
沙发
 楼主| 发表于 2015-3-17 02:09:12 | 显示全部楼层
要学会通过各种方法将面前的事情变成自己感兴趣的,那专研起来就不会是无聊和折磨了。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|仓酷云 鄂ICP备14007578号-2

GMT+8, 2024-5-2 23:24

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表