Преимущества КВК - PullRequest
       25

Преимущества КВК

2 голосов
/ 16 мая 2019

Я пытался понять это некоторое время, но не могу понять преимущества KVC, кроме:

  1. Проверки компилятора (таким образом избегая строкового кода)
  2. Используется с КВО

Я не уверен, есть ли какое-либо преимущество использования 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] / * возвращает строку «Джон» * /

вместо:

profile1.firstName // возвращает строку "Джон"

И если у кого-то есть примеры / примеры кода, то если они смогут объяснить это с помощью swift, это было бы здорово (так как мой Objective-C не очень хорош)

1 Ответ

2 голосов
/ 24 мая 2019

Пример, который вы использовали, не является оптимальным случаем использования 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 - Пол Хадсон

...