美文网首页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