KVC的优势

时间:2019-05-16 10:10:40

标签: swift swift-keypath

一段时间以来,我一直在试图解决这个问题,但是除了:: p之外,我还无法理解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" */

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

  

让firstNameKey = \ Profile.firstName

     

profile1 [keyPath:firstNameKey]   / *返回字符串“ John” * /

而不是:

  

profile1.firstName //返回字符串“ John”

如果某人有一些代码示例/示例,那么如果他们可以使用swift对其进行解释,那将会很棒(因为我的Objective-C不好)

1 个答案:

答案 0 :(得分:2)

您使用的示例并非使用 KVC keyPath 本身的最佳情况。

使用协议时, keyPath 的真正威力将得到释放。让我举一个例子-

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

protocol Identifiable {
    var id: Int { get }
}

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

在这里,具有成员Person的{​​{1}}类型听起来不太好。考虑另一个-

id

在这里,struct Book: Identifiable { var id: Int var title: String var author: String } 可以唯一标识一本书,但这听起来并不好。

这是 keyPath 发挥作用的地方。

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

id

另一个优点是,符合条件的类型可以具有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")) idString任何类型的Int,而不是仅Int(以前的情况)

如果您只想给id指定一种特定类型,只说Int,则可以用此协议代替我们的协议定义-

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

这将强制符合条件的类型使用Int代替其id

来源-Swift KeyPath - Paul Hudson