KVC编码协议,iOS 中对象之间有哪些通信方式

1,iOS 中对象之间有哪些通信方式1)delegate:代理是一种设计模式 , 它是通过被代理者定义代理协议委托代理者实现协议,用于两个对象间的通信交互 。在 IOS 中 delegate 主要用于视图与使用对象之间的通信交互,delegate 的效率是最高的,典型的特就是它有返回值 。block:block 类似与函数 , 可作为参数进行传递用于回调,block 可以定义在方法里,函数不能 。block 语法简单 , 写在方法里可以访问局部变量可以使代码更加的紧凑,结构化 。相对于 delegate,block 不用建立代理协议,使用简单 。通知:NSnotification 一个中心对象注册和发送通知,所用的其他的对象都可以收到通知 。KVC:键-值编码是用于间接访问对象属性的机制 , 并不需要调用 set 或者 get 方法访问变量,是通过 set value for key 进行间接访问实例变量 。{0}
2,什么是KVC在iOS开发过程中,我们经常会听到或者用到KVO/KVC,但是对于什么是KVO和KVC,我们可能没有那么了解 。下面先让我们来了解一下什么是KVC.什么是KVC在苹果的官方文档中是这样描述KVC的:它是一种通过字符串描述符而不是通过调用访问方法或者直接使用实例变量的非直接的访问对象属性的机制,说白了就是KVO是一种通过非常规方法访问成员变量或者属性的机制,这种非常规方式就是通过一个字符串标示符也就是所谓的key来访问属性或者成员变量 。而这个key一般就是属性名或者实例变量名 。对于KVC的基本的方法都定义在NSKeyValueCoding的非正式协议中 , 并且NSObject默认实现了该协议 。KVC不仅支持对象类型,也支持数值类型和结构体 。非对象类型的参数和返回类型会自动封装成NSValue或NSNumber类型 。KVO可以用来访问三种不同的对象值类型:属性、一对一关系、一对多关系属性可以是诸如数值、字符串、bool类型等简单的值 。也可以NSNumber或者NSColor这样的对象值 。在一对一关系里的对象可以拥有它自己的属性 , 这些属性可以在不改变对象的情况下被改变 。像UIView的superView的属性,我们可以更改superView的属性,而不需要更改UIView 。一对多属性是一些相关对象的集合 。通常用NSArray或者NSSet来存储这些集合 。KVO也允许用户自定义集合类 , 但依然是像访问NSArray或者NSSet一样访问它们 。键和键路径键是用来标识一个对象属性的字符串 。一般情况下,键就是访问方法或者是对象的实例变量的名字 。键必须是ASCII编码,以小写字母开头,并且不能包含空格 。举几个键的例子:age、firstName、lastNmame等 。键路径是一串由点分隔的键组成的字符串,它是用来遍历一系列的对象属性的 。第一个键的属性是跟接收者相关的 , 而每一个子系列是跟前一个属性相关的 。比如键路径address.street,这个键路径会首先从接收者获得address属性,然后从address属性中获得street属性 。用KVC获得属性的值方法valueForKey:会返回跟接收者相关的key的值 。如果对于指定的key没有访问器或者实例变量 , 则给自己发送一个valueForUndefinedKey:消息,这个方法的默认实现是抛出一个NSUndefinedKeyException 。子类可以重写这个方法 。同样的,valueForKeyPath:返回跟接收者相关的键路径的值 。对于子系列中任何不遵循KVC的对象 , 都会收到一个valueForUndefineKey:消息 。dictionaryWithValuesForKeys:会检索数组中所有跟接收者相关的key的值 。返回的NSDictionary中包含了数组中所有key的值 。注意:集合对象,比如NSArray、NSSet和NSDictionary中不能将nil作为一个值 。相反的,应该用NSNull对象代替nil 。NSNull是一个代表nil的对象属性 。dictionaryWithValuesForKeys:和setValuesForKeysWithDictionary:方法的实现中,默认会在nil和NSNull之间进行转换 。在你的对象中,不需要对nil做显示的测试 。用KVC设置属性的值方法setValue:forKey:是将接收者中相关key的值设置成指定的值 。在这个方法的实现中 , 会将NSValue的值转换成普通的数值然后赋给属性 。如果指定的key不存在,会给接收者发送一个setValue:forUndefinedKey:消息 。这个方法的默认实现是抛出一个NSUndefinedKeyException异常,子类可以重写这个方法来自定义默认行为 。方法setValue:forKeyPath:的实现跟前面的一样 , 只不过它是用来处理键路径的 。setValuesForKeysWithDictionary:方法是用指定字典里的值来赋给接收者相关的属性 。这个方法的默认实现是对每一对键-值都调用一次setValue:forKey:方法,并且自动将nil转成NSNull 。最后,你要关心的当尝试将一个nil值赋给一个非对象类型的时候该怎么办 。这种情况下,接收者会发出一个setNilValueForKey:消息 , 这个方法的默认实现是抛出一个NSInvalidArgumentException 。在你的应用中可以重写这个方法来定义一个默认值,然后用新的值触发setValue:forKey{1}
3 , iOS中的KVC简介Key-Value Coding俗称"键值编码",苹果官方简称这个模式为KVC编码模式,也就是说可以通过一个Key去访问某一个属性,或者给对象去赋值,而不需要去明确存取方法,这样就可以动态的访问和修改对象的属性,而不是在编译的时候去确定,这也是iOS开发中的一大便利,其实有很多的框架和功能是用KVC去实现的,这个技术存在已经很长时间了 , 在网上也有很多相关的教程去教童鞋们如何去使用KVC,在这里,我们就只是简单的介绍一下KVC的底层实现和使用方法 。从苹果官方对KVC的解释来看,其实KVC在Fundation框架中占有很高的地位,诸如Core-Data之类的框架都使用到了KVC技术,我们在开发中可能常见的API有:NSKeyValueCoding类别中还有其他的一些比较重要方法,如下:说起KVC的执行流程,我们有很多初级工程师都不大清楚,只知道KVC是如何使用的 , 而不知道KVC是怎么Key的寻找策略的 。下图我们借鉴了MJ老师的两幅PPT来解释上图我们可以看到简单说KVC机制在设值的时候会按照 set<Key>: 》_set<Key> 》_<key> 》_is<Key> 》<key> 》 is<Key> 顺序搜索成员并进行赋值操作,但是如果开发者重写了类方法+ (BOOL)accessInstanceVarialbesDirectly并且让其返回NO,这样在搜索的时候会直接从步骤 1跳转到步骤5。举一个例子,我们先创建一个Person类然后用KVC赋值最终在控制台打印的结果是当调用valueForKey:方法时,KVC对key的搜索顺序有点不同于setValue:forKey:方法,大致步骤如下:如最终打印为上述可以看出,当Key查找不到值的时候会走 valueForUndefinedKey 方法中抛出异常类的成员变量有可能是自定义类或其他复杂数据类型,对这种成员变量可以先用KVC获取该属性,然后再用KVC来获取这个自定义类的属性 , 这样一层层去获取,但这样比较繁琐 。对此KVC提供一个解决方案 , 就是键路径keyPath,顾名思义就是按照路径寻找key 。主要有两个以下两个方法:在上述Person中我们创建一个Cat类在Cat类中我们创建一个属性 name我们如果需要用KVC对Person对象中Cat对象赋值的话,我们就必须用到KeyPath了KVC对于keyPath的搜索机制第一步就是分离key , 用小数点.来分割key,然后再像普通key一样按照上面介绍的顺序搜索 。使用KVC过程中最常见的异常就是不小心使用了错误的key,或者在设值中不小心传了nil的值,KVC有专门的方法处理这些异常 。该方法返回一个可变有序数组 。对于无序的容器,可以用以下方法:该方法返回一个可变的无序集合 。同时他们也有对应的keyPath版本:当NSDictionary对象使用KVC时,valueForKey:的表现行为和objectForKey:一样,使用valueForKeyPath:可访问多层嵌套的字典会方便点,在KVC中有两个关于NSDictionary的方法:当开发者需要验证能不能用KVC设定某个值时,就需要在进行KVC赋值前验证值value的有效性,API文档里面提供下面的方法进行判断值的有效性 。该方法的工作原理:先找一下你的类中是否实现了方法-(BOOL)validate<Key>:error:,如果实现了就会根据实现方法里面的自定义逻辑返回NO或者YES,如果没有实现这个方法,则系统默认返回就是YES 。输出结果为这里首先调用方法 [self validateValue:&value forKey:key error:&error] ; , 这里,由于我实现了方法-(BOOL)validatePersonName:(id *)value error:(out NSError * _Nullable __autoreleasing *)outError ,所以就在这里进行值value有效性的判断,这里 [name isEqualToString:@"小明"] 我就给返回YES,否则就返回NO 。KVC在iOS开发中非常的灵活,提供了开发者更多的赋值和取值操作的选择,它的有点明显 , 缺点也有,如果key只写错,编写的时候不会报错 , 但是运行的时候会报错,在实际开发中需要开发者时刻小心自己输入的键值 , 也时刻提醒着开发者一旦使用KVC就要做容错处理 。【KVC编码协议,iOS 中对象之间有哪些通信方式】{2}

    推荐阅读