KeyValueCoding,键值对编码。我们一般称之为KVC,一般与KVO一起使用。本文主要讲KVC的方法使用。
以下两个网址记录了一些我没有写的东西。太懒了。
https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/KeyValueCoding/SearchImplementation.html#//apple_ref/doc/uid/20000955
https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/KeyValueCoding/CollectionOperators.html#//apple_ref/doc/uid/20002176-BAJEAIEE
Swift使用KVC的时候需要对该类做处理
@objcMembers class KVCModel: NSObject {
var alllalal : String?
var name : String?
var sex : String?
var son : SonModel!
}
属性一:accessInstanceVariablesDirectly
当accessInstanceVariablesDirectly为yes时。 valueForKey:&setValue:forKey:& mutableArrayValueForKey:&mutableOrderedSetValueForKey:&mutableSetValueForKey:等方法会进行实例变量搜素。
方法一:获取到指定key对应的value。
OC写法
- (id)valueForKey:(NSString *)key;
label.text = [model valueForKey:@"name"];
Swift写法
func value(forKey key: String) -> Any?
label.text = model.value(forKey: "name") as? String
这个方法返回的是可空类型,所以必要的时候加个!
搜索顺序。
1.查找有没有get<Key>, <key>, is<Key>, _<key>为名的方法,如果有,直接到第5步。
2..如果1没找到,查找有没有countOf<Key> and objectIn<Key>AtIndex:and <key>AtIndexes:为名的方法。 如果能找到第一个,以及其他两个里面的至少一个。
- 如果2没找到,countOf<Key>, enumeratorOf<Key>, 和 memberOf<Key>:
方法二:获取到指定key path对应的value。
OC写法
- (id)valueForKeyPath:(NSString *)keyPath;
label.text = [model valueForKeyPath:@"son.name"];
Swift写法
func value(forKeyPath keyPath: String) -> Any?
print(model.value(forKeyPath: "son.name"))
这个方法返回的是可空类型,所以必要的时候加个!
方法三:返回一个字典,其中包含的属性值被给定数组中的每个键。
OC写法
- (NSDictionary<NSString *,id> *)dictionaryWithValuesForKeys:(NSArray<NSString *> *)keys;
NSLog(@"%@", [model dictionaryWithValuesForKeys:@[@"name", @"sex123", @"classroom", @"height"]]);
Swift写法
func dictionaryWithValues(forKeys keys: [String]) -> [String : Any]
print(model.dictionaryWithValues(forKeys: ["alllalal", "name", "sex", "abc"]))
方法四:调用valueForKey:当它发现没有属性对应于一个给定的键。
当以上三个方法使用的时候找不到对应的key。如果没有重写方法四就会崩溃。
OC写法
- (id)valueForUndefinedKey:(NSString *)key;
- (id)valueForUndefinedKey:(NSString *)key {
if ([key isEqualToString:@"sex123"]) {
return @"666";
}
return nil;
}
Swift写法
func value(forUndefinedKey key: String) -> Any?
override func value(forUndefinedKey key: String) -> Any? {
return "qweqwe"
}
方法五:返回一个对应的key的可变数组
OC写法
- (NSMutableArray *)mutableArrayValueForKey:(NSString *)key;
[[model mutableArrayValueForKey:@"girlFriends"] insertObject:@"999" atIndex:2];
[model mutableArrayValueForKey:@"girlFriends"][0] = @"jdx";
Swift写法
func mutableArrayValue(forKey key: String) -> NSMutableArray
override func value(forUndefinedKey key: String) -> Any? {
return "qweqwe"
}
搜索顺序。
1.寻找一对方法名像insertObject:in<Key>AtIndex: 和removeObjectFrom<Key>AtIndex:或者方法名像 insert<Key>:atIndexes: 和 remove<Key>AtIndexes: 如果对象有至少一个插入方法和至少一个删除方法,则返回一个代理对象,该代理对象通过发送<Key>AtIndex:, removeObjectFrom<Key>AtIndex:,插入<Key>:atIndexes:,并将<Key bbbb> atIndexes:将消息删除给mulearb3的原始接收者。
当接收mutableArrayValueForKey: message的对象还实现了一个可选的替换对象方法,其名称为replaceObjectIn<Key>AtIndex:with object:或replace<Key>AtIndexes:with<Key>:,代理对象在适合最佳性能时也会使用这些方法。
2.如果对象没有可变数组方法,那么应该寻找一个访问器方法,该方法的名称与模式集<Key>: >匹配。在本例中,返回一个代理对象,该对象通过向mutableArrayValueForKey:的原始接收者发出一个set<Key>: message来响应NSMutableArray消息。
3.如果既找不到可变数组方法,也找不到访问器,如果接收者的类直接对accessinstancevariablesdirect响应为YES,那么按这个顺序搜索一个名为_<key>或<key>的实例变量。
如果找到这样的实例变量,则返回一个代理对象,该对象将接收到的每个NSMutableArray消息发送到实例变量的值,该值通常是NSMutableArray或其子类的一个实例。
4.如果所有其他方法都失败,则返回一个可变集合代理对象,该对象发出setValue:forUndefinedKey:消息给mutableArrayValueForKey: message的原始接收者,当它收到NSMutableArray消息时。
setValue:forUndefinedKey:的默认实现会引发一个NSUndefinedKeyException异常,但是子类可以会覆盖这个行为。
方法六:获取到指定key path对应的可变数组
Swift写法
func mutableArrayValue(forKeyPath keyPath: String) -> NSMutableArray
mutableArray = model2.mutableArrayValue(forKeyPath: "superArray.array")
方法七:mutableSetValueForKey:
Swift
func mutableSetValue(forKey key: String) -> NSMutableSet
var mutableSet = model.mutableSetValue(forKey: "set")
方法八:mutableSetValueForKeyPath:
Swift
func mutableSetValue(forKeyPath keyPath: String) -> NSMutableSet
var mutableSet = model.mutableSetValue(forKey: "superArray.set")
方法九:mutableOrderedSetValueForKey:
Swift
- (NSMutableOrderedSet *)mutableOrderedSetValueForKey:(NSString *)key
var mutableOrderedSet = model.mutableOrderedSetValue(forKey: "array")
方法十:mutableOrderedSetValueForKeyPath:
Discussion:orderedSet和nsarray类型的属性都可以被这个方法所转成mutableOrderedSet.因为第一步找的方法都是insertObject:in<Key>AtIndex: 和 removeObjectFrom<Key>AtIndex:。
Swift
- (NSMutableOrderedSet *)mutableOrderedSetValueForKeyPath:(NSString *)keyPath
var mutableOrderedSet = model.mutableOrderedSetValue(forKeyPath: "superArray.array")
方法十一:setValue:forKey:
OC
- (void)setValue:(id)value forKey:(NSString *)key;
[theModel setValue:modelArray forKey:@"ag"];
方法十二:setValue:forKeyPath:
OC
- (void)setValue:(id)value forKeyPath:(NSString *)keyPath;
[theModel setValue:modelArray forKeyPath:@"sonModel.array"];
方法十三:setValuesForKeysWithDictionary:
OC
Discussion:这个字典的key是属性名value是属性值。注意key只能是NSString *
- (void)setValuesForKeysWithDictionary:(NSDictionary<NSString *,id> *)keyedValues;
[theModel setValuesForKeysWithDictionary:@{@"name" : @"qqq",
@"array" : modelArray
}];
方法十四:setNilValueForKey:
Discussion:由KVC的子类实现。比如给一个assign的属性设置一个nil。就会走这个方法。
OC
- (void)setNilValueForKey:(NSString *)key;
[theModel setValue:nil forKey:@"age"];
- (void)setNilValueForKey:(NSString *)key {
[self setValue:@0 forKey:@"age"];
}
方法十五:setValue:forUndefinedKey:
Discussion:由KVC的子类实现。如果set的key找不到的话。就调用这个方法。
OC
- (void)setValue:(id)value forUndefinedKey:(NSString *)key;
[theModel setValue:@"打死死猪精" forKey:@"ge"];
- (void)setValue:(id)value forUndefinedKey:(NSString *)key {
if ([key isEqualToString:@"ge"]) {
self.name = value;
}
}
//死猪精是我们的UI。。。我写页面布局她说她都能写。。。然后我说不好改的布局她说很好改。。。然后让她改她说她看代码头疼。
方法十六:validateValue:forKey:error:和validateValue:forKeyPath:error:
Discussion:这就是KVV。如何调用验证方法?第一种是直接调用验证方法validate<Key>:error:,第二种则是通过validateValue:forKey:error:,它会自动寻找到对应的validate<Key>:error:方法去执行验证。如果不能找到对应的方法,则会返回YES,并且验证值。
OC
- (BOOL)validateValue:(inout id _Nullable *)ioValue forKey:(NSString *)inKey error:(out NSError * _Nullable *)outError;
[theModel validateValue:&modelArray forKey:@"ge" error:&error];
注意这个ioValue是A pointer to a new value.就是我们要给的value的指针。
网友评论