美文网首页KVC
KVC - Software Design

KVC - Software Design

作者: ienos | 来源:发表于2021-07-22 20:49 被阅读0次
    Mind map

    其实是一种基于 NSObject 查询对象属性的机制


    现在我们从代码设计的角度来分析 KVC

    1. Key & Value

    例如类 Person 如下:

    Class Person: NSObject {
          var name: String = ""
          var age: Int = 0
    }
    

    比如说 Person 对象有 name 属性,我们想通过某个 API 来获取,或者设置 name 的值,即:

    • set "ienos" For Name
    • get String For Name

    抽象化该方法表示为(Key 为字符串):

    • setValue:forKey:
    • valueForKey:

    那么我们就可以通过 Key 为 name,来寻找对应的 value,获取对应的属性值
    或者通过 Key 来设置 value 的值,从而对属性进行赋值

    另外为了防止我们对不存在的 Key 进行操作,这里引入验证 Key 是否有效的 API

    • validateValue:forKey:error:

    2. Key Undefiend

    如果 Key 不存在如何处理?

    • 提示开发者 Key 不存在,抛异常
    • 允许开发者自定义映射 Key

    2.1 valueForUndefinedKey:

    比如说客户端从云端请求到的 JSON 为 ["Name": "ienos"]

    通过解析,我们需要将 JSON 中的 Name 映射到 Person 的 name

    那么此时开发者需要可以自定义该映射表

    因此开放 valueForUndefinedKey:允许开发者重写该方法,自定义映射表

    - (void)setValue:(id)value forKey:(NSString *)key {
        if ([key isEqualToString:@"Name"]) {
            key = @"name";
        }
        [super setValue:value forKey:key];
    }
    

    3. Value Type

    在设计 Value 时,考虑到 Value 有可能为:对象类型基本数据类型

    在 Objective-C 中,如果要同时满足 Value 为 对象类型基本数据类型 如何处理?

    • Value 为 id 类型,对象保持原有的类
    • 对于基本数据类型:int、float、char etc. 还有结构体 struct
    • int、float、char etc 用 NSNumber 表示
    • struct 用 NSValue 表示

    那当 setValue 为 nil 时,需不需要处理?

    • setValue:ForKey 为 nil,此时对于基本数据类型不存在值则抛出异常。
    • 针对这种情况需要提供开发者可重写方法,默认抛出异常

    重写可为 Key 设置默认值 setNilValueForKey:

    4. 多 Key 赋值,取值

    如果我们需要对多个 Key 进行赋值怎么办? 或者说获取部分 Key 对应的值

    • setValuesForKeysWithDictionary:
    • dictionaryWithValuesForKeys:

    5. KeyPath

    当我们的类有多层结构,那么我们应该如何设计?

    假如 Person 新增一个 company(Company类) 的属性

    class Person: NSObject {
        var name: String = ""
        var age: Int = 0
        var company: Company = Company.init()
    }
             
    class Company: NSObject {
        var name: String = ""
    }
    

    那原有的 setValue:forKey 就不再适用,我们引入 keyPath 的概念

    通过路径的方式访问 Key

    • setValue:forKeyPath:
    • valueForKeyPath:
    let person = Person.init()
    person.company.name = "Apple"
    person.setValue("Apple", forKeyPath: "company.name")
    person.valueForKeyPath("company.name")
    

    keypath 通过寻址的过程,内部实现依旧调用 setValue:forKey

    4. Collection Value

    假如 Person 新增一个 family 数组属性

    class Person: NSObject {
        var name: String = ""
        var age: Int = 0
        var company: Company = Company.init()
        var cardIdentifies: [String] = []
    }
             
    class Company: NSObject {
        var name: String = ""
    }
    

    也就是说 Person 类中有一个 cardIdentifies 的属性,其中 cardIdentifies 是个数组且元素为字符串实例对象

    valueForKey: 返回的是 id 类型

    如果我使用 valueForKey("cardIdentifies") 还需要转类型转为 Array

    对于经常操作 Array 的开发者不够友好

    所以需要新增对集合元素的 API

    // Array
    - mutableArrayValueKey:  / mutableArrayValueForKeyPath:
    // Set
    - mutableSetValueForKey: / mutableSetValueForKeyPath:
    // OrderedSet
    - mutableOrderedSetValueForKey: / mutableOrderedSetValueForKeyPath:
    

    5. Collection Operators

    为了方便集合类型的操作,引入 Collection Operators

    Operator key path format

    例如:

    • 计算平均值 transactions.value(forKeyPath: "@avg.amount")
    • 计算总数 transactions.value(forKeyPath: "@count")

    详细 API 见 [iOS - Key Value Coding]

    相关文章

      网友评论

        本文标题:KVC - Software Design

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