KVC的优势

Advantages of KVC

我已经尝试解决这个问题一段时间了,但除了 :

之外无法理解 KVC 的优势
  1. 编译器检查(从而避免字符串类型的代码)
  2. 与 KVO 一起使用

除了上述两种情况(我知道我可能错了),我不确定使用 KVC 是否有任何优势,但我找不到!

喜欢考虑以下代码:

class Profile: NSObject {
    
    @objc var firstName: String
    var lastName: String
    
    init(firstName: String,lastName: String) {
        self.firstName = firstName
        self.lastName = lastName
        super.init()
    }
    
}

let profile1 = Profile(firstName: "John", lastName: "Doe")

profile1.firstName // returns String "John"

profile1.value(forKey: "firstName") // returns Optional<Any> 

let firstNameKey = \Profile.firstName
profile1[keyPath: firstNameKey] /* returns String "John" */

我的意思是我为什么要使用:

let firstNameKey = \Profile.firstName

profile1[keyPath: firstNameKey] /* returns String "John" */

而不是:

profile1.firstName // returns String "John"

如果有人有一些代码 sample/examples,那么如果他们可以使用 swift 来解释它,那就太好了(因为我的 Objective-C 不好)

您使用的示例不是使用 KVCkeyPath 本身的最佳情况。

当您使用 protocols 时,keyPath 的真正力量 IMO 会释放出来。让我举个例子-

假设您有一个协议 Identifiable,它只有一个成员 - id。符合此要求的每种类型都必须使用 id 属性 来唯一标识它。

protocol Identifiable {
    var id: Int { get }
}

struct Person: Identifiable {
    var id: Int
    var name: String
}

在这里,具有成员 idPerson 类型听起来不太好。考虑另一个 -

struct Book: Identifiable {
    var id: Int
    var title: String
    var author: String 
}

在这里,一本书也可以通过 id 唯一标识,但听起来不太好。

这就是 keyPath 发挥作用的地方。

您可以在协议内部定义成员,并使用某个名称让符合类型为该特定协议成员编写自己的名称。符合类型可以映射或告诉编译器它们的特定成员是使用 keyPath.

协议内部成员的替换
protocol Identifiable {
    associatedtype ID
    static var id: WritableKeyPath<Self,ID> { get }
}

struct Person: Identifiable {
    static var id = \Person.socialSecurityNumber

    var socialSecurityNumber: Int
    var name: String
}

struct Book: Identifiable {
    static var id = \Book.isbn

    var isbn: String
    var title: String
    var author: String
}

func printID<T: Identifiable>(aType: T) {
    print(aType[keyPath: T.id])
}

printID(aType: Person(socialSecurityNumber: 1234, name: "Shubham Bakshi"))
printID(aType: Book(isbn: "qwertyui", title: "The Theory of Everything", author: "Stephen W. Hawking"))

作为一个额外的优势,您的符合类型可以具有任何类型的 idStringInt 而不是仅 Int(如前例所示)

如果你只想给id一个特定的类型,只说Int,你可以用这个替换我们协议的定义 -

protocol Identifiable {
    static var id: WritableKeyPath<Self,Int> { get }
}

这将强制符合类型使用 Int 作为它们的 id 替代品。

来源 - Swift KeyPath - Paul Hudson