Пример, который вы использовали, не является оптимальным случаем использования KVC или keyPath .
Истинная сила, IMO, keyPath раскрывается, когда вы работаете с протоколами . Позвольте привести пример -
Скажем, у вас есть протокол Identifiable
, в котором есть только один участник - id
. Каждый тип, который соответствует этому, должен использовать свойство id
, которое однозначно идентифицирует его.
protocol Identifiable {
var id: Int { get }
}
struct Person: Identifiable {
var id: Int
var name: String
}
Здесь тип Person
, имеющий член id
, звучит не слишком хорошо. Рассмотрим еще один -
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"))
В качестве дополнительного преимущества ваш соответствующий тип может иметь id
любого типа, String
, Int
, а не только Int
(как было в предыдущем случае)
Если вы хотите присвоить id
только определенный тип, скажем, только Int
, вы можете заменить определение нашего протокола на это -
protocol Identifiable {
static var id: WritableKeyPath<Self,Int> { get }
}
Это заставит соответствующие типы использовать Int
для их id
замены.
Источник - Swift KeyPath - Пол Хадсон