苹果的面向对象开发框架,用来生成 Mac OS X 的应用程序。基本的开发语言为 Objective-c, 一个c 的超集。
即为:Coroa 基本面向原生的API抽象。是C的一个超级。
在Cocoa中是以被万物之源NSObject类实现的NSKeyValueCoding(键值编码)/(键值观察)NSKeyValueObserving 非正式协议 的形式被定义为基础框架的一部分。
=
NSKeyValueCoding 是一个非正式的协议。(线管的内容能够看西面罗列的方法)
KVC/KVO实现的根本是Objective-C的 动态性和runtime
KVC/KVO机制离不开訪问器方法的实现。
kvc
相似c++中的map类的使用。
它提供了一种使用“字符串”而不是“訪问器(方法)”方法去訪问一个对象实例变量的机制。
kvo
提供了一种当其他对象属性被改动的时候能通知当前对象的机制.
KVO机制非常适合实现model和controller类之间的通讯。
总结全部的方法差点儿能够使用以下的四个方法为代表。
//一般的都是这几个方法 <span style="color:#990000;">- (id)valueForKey:(NSString *)key; - (void)setValue:(id)value forKey:(NSString *)key;</span> Key——>键值 , 就是要訪问的属性名称(key)相应的字符串。(用数组(索引)的方式似乎没有什么区别) <span style="color:#CC0000;">- (id)valueForKeyPath:(NSString *)keyPath; - (void)setValue:(id)value forKeyPath:(NSString *)keyPath;</span> 后面的KeyPath是一个被点操作符隔开的用于訪问对象的指定属性的字符串序列。(keypath 就是大范围到小范围逐渐到详细的地方) eg:eyPath address.street将会訪问消息接收对象所包括的address属性中包括的一个street属性。 事实上KeyPath说白了就是我们平时使用点操作訪问某个对象的属性时所写的那个字符串。
点语法和kvc之间的区别:
在实现了訪问器方法的类中,使用点语法和KVC訪问对象事实上区别不大,二者能够随意混用。可是没有訪问起方法的类中,点语法无法使用,这时KVC就有优势了。( 原因见第三部分的第一节:KVC怎样訪问属性值。
) ??
一对多的关系:(数据中常常会存在)
①间接操作
先通过KVC方法取到集合属性,然后通过集合属性操作集合中的元素。
②直接操作 (基本上是不适用)
4、键值验证(Key-Value Validation)
KVC提供了验证Key相应的Value是否可用的方法:
- (BOOL)validateValue:(inout id *)ioValue forKey:(NSString *)inKey error:(out NSError **)outError;
该方法默认的实现是调用一个例如以下格式的方法:
- (BOOL)validate<Key>:error:
比方属性name相应的方法为:
-(BOOL)validateName:(id *)ioValue error:(NSError * __autoreleasing *)outError {
return ;
}
KVC是不会自己主动调用键值验证方法的 。就是说我们须要手动验证。可是有些技术,比方CoreData会自己主动调用。
5、KVC对数值和结构体型属性的支持
总结一下,想使用KVO有三种方法:
1)使用了KVC
使用了KVC,假设有訪问器方法,则执行时会在訪问器方法中调用 will/didChangeValueForKey:方法;
没用訪问器方法,执行时会在setValue:forKey方法中调用 will/didChangeValueForKey:方法。
2)有訪问器方法
执行时会重写訪问器方法调用 will/didChangeValueForKey:方法。
因此,直接调用訪问器方法改变属性值时,KVO也能监听到。
3)显示调用will/didChangeValueForKey:方法。
总之。想使用KVO,仅仅要有 will/didChangeValueForKey:方法就能够了。
③ _isKVOA
这个私有方法预计是用来标示该类是一个 KVO 机制声称的类。
长处和缺点
1、长处①能够再非常大程度上简化代码
样例网上非常多。这就不举了
②能跟脚本语言非常好的配合
才疏学浅,没学过AppleScript等脚本语言,所以没能深刻体会到该长处。
2、缺点
KVC的缺点不明显,基本的kvo的缺点如连接:http://www.mikeash.com/pyblog/key-value-observing-done-right.html
核心思想是说KVO的回调机制,不能传一个selector或者block作为回调。而必须重写-addObserver:forKeyPath:options:context:方法所引发的一系列问题。问了解决问题。作者还亲自实现了一个MAKVONotificationCenter类。代码见github:
https://github.com/mikeash/MAKVONotificationCenter
只是个人觉得这仅仅是苹果做的KVO不够完美,不能算是缺陷。
关于NSKeyValueCoding.h这个文件爱你的属性的了解。
#import <Foundation/NSArray.h> #import <Foundation/NSDictionary.h> #import <Foundation/NSOrderedSet.h> #import <Foundation/NSSet.h> @class NSError, NSString; FOUNDATION_EXPORT NSString *const NSUndefinedKeyException; FOUNDATION_EXPORT NSString *const NSAverageKeyValueOperator; FOUNDATION_EXPORT NSString *const NSCountKeyValueOperator; FOUNDATION_EXPORT NSString *const NSDistinctUnionOfArraysKeyValueOperator; FOUNDATION_EXPORT NSString *const NSDistinctUnionOfObjectsKeyValueOperator; FOUNDATION_EXPORT NSString *const NSDistinctUnionOfSetsKeyValueOperator; FOUNDATION_EXPORT NSString *const NSMaximumKeyValueOperator; FOUNDATION_EXPORT NSString *const NSMinimumKeyValueOperator; FOUNDATION_EXPORT NSString *const NSSumKeyValueOperator; FOUNDATION_EXPORT NSString *const NSUnionOfArraysKeyValueOperator; FOUNDATION_EXPORT NSString *const NSUnionOfObjectsKeyValueOperator; FOUNDATION_EXPORT NSString *const NSUnionOfSetsKeyValueOperator; @interface NSObject(NSKeyValueCoding) + (BOOL)accessInstanceVariablesDirectly; - (id)valueForKey:(NSString *)key; - (void)setValue:(id)value forKey:(NSString *)key; - (BOOL)validateValue:(inout id *)ioValue forKey:(NSString *)inKey error:(out NSError **)outError; - (NSMutableArray *)mutableArrayValueForKey:(NSString *)key; - (NSMutableOrderedSet *)mutableOrderedSetValueForKey:(NSString *)key NS_AVAILABLE(10_7, 5_0); - (NSMutableSet *)mutableSetValueForKey:(NSString *)key; - (id)valueForKeyPath:(NSString *)keyPath; //这个是有关路径的字符串。这个是怎么用的? - (void)setValue:(id)value forKeyPath:(NSString *)keyPath; - (BOOL)validateValue:(inout id *)ioValue forKeyPath:(NSString *)inKeyPath error:(out NSError **)outError; - (NSMutableArray *)mutableArrayValueForKeyPath:(NSString *)keyPath; - (NSMutableOrderedSet *)mutableOrderedSetValueForKeyPath:(NSString *)keyPath NS_AVAILABLE(10_7, 5_0); - (NSMutableSet *)mutableSetValueForKeyPath:(NSString *)keyPath; - (id)valueForUndefinedKey:(NSString *)key; - (void)setValue:(id)value forUndefinedKey:(NSString *)key; - (void)setNilValueForKey:(NSString *)key; - (NSDictionary *)dictionaryWithValuesForKeys:(NSArray *)keys; - (void)setValuesForKeysWithDictionary:(NSDictionary *)keyedValues; @end //定的数组 @interface NSArray(NSKeyValueCoding) - (id)valueForKey:(NSString *)key; - (void)setValue:(id)value forKey:(NSString *)key; @end //字典的两种方式进行组合 @interface NSDictionary(NSKeyValueCoding) - (id)valueForKey:(NSString *)key; @end @interface NSMutableDictionary(NSKeyValueCoding) - (void)setValue:(id)value forKey:(NSString *)key; @end @interface NSOrderedSet(NSKeyValueCoding) - (id)valueForKey:(NSString *)key; - (void)setValue:(id)value forKey:(NSString *)key; @end @interface NSSet(NSKeyValueCoding) - (id)valueForKey:(NSString *)key; - (void)setValue:(id)value forKey:(NSString *)key; @end #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) //TARGET_OS_EMBEDDED这个表示是嵌入式的方式 //TARGET_OS_IPHONE iphone 开发 //TARGET_OS_MAC os系统开发 @interface NSObject(NSDeprecatedKeyValueCoding) + (BOOL)useStoredAccessor ; - (id)storedValueForKey:(NSString *)key ; - (void)takeStoredValue:(id)value forKey:(NSString *)key; - (void)takeValue:(id)value forKey:(NSString *)key ; - (void)takeValue:(id)value forKeyPath:(NSString *)keyPath ; - (id)handleQueryWithUnboundKey:(NSString *)key; - (void)handleTakeValue:(id)value forUnboundKey:(NSString *)key; - (void)unableToSetNilForKey:(NSString *)key; - (NSDictionary *)valuesForKeys:(NSArray *)keys ; - (void)takeValuesFromDictionary:(NSDictionary *)properties; @end #endif