美文网首页
NSKeyValueCoding--KVC OC&Swift

NSKeyValueCoding--KVC OC&Swift

作者: 527267线的iOS工程师 | 来源:发表于2018-07-07 10:27 被阅读0次

    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:为名的方法。 如果能找到第一个,以及其他两个里面的至少一个。

    1. 如果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的指针。
    

    相关文章

      网友评论

          本文标题:NSKeyValueCoding--KVC OC&Swift

          本文链接:https://www.haomeiwen.com/subject/vhgeqftx.html