๐Ÿ”ฐKey Path

Keypaths allow you to refer to properties without invoking them โ€“ you hold a reference to the property itself, rather than reading its value.

Key paths ไธป่ฆไธ‰็จฎ่ฎŠ้ซ”(้‚„ๆœ‰ๅ…ถไป–)

  • KeyPath: read-only access to a property.

  • WritableKeyPath: readwrite access to a mutable property with value semantics (so the instance in question also needs to be mutable for writes to be allowed).

  • ReferenceWritableKeyPath: can only be used with reference types, and provides readwrite access to any mutable property.

Keypaths in Swift have a few more types, which mostly revolve around type-erasure, like with Any. When you combine or allow multiple keypaths, for example in an array, you can use the PartialKeyPath and AnyKeyPath to construct types that fit multiple keypaths.

Examples

๐Ÿ‘‰ replit

// โญ ไธ‹้ขๅ…ฉ็จฎๅž‹ๅˆฅ้›–็„ถ้ƒฝๆœ‰ใ€Œๅฏไปฅ็•ถไฝœ IDใ€็š„ๅฑฌๆ€ง๏ผŒไฝ†ๅฑฌๆ€งๅ็จฑไธไธ€ๆจฃใ€‚

struct Person {
    // social security number
    var ssn: String         // โญ id key for `Person`
    var name: String
}

struct Book {
    var isbn: String        // โญ id key for `Book`
    var title: String
}

/* -------- HasID protocol -------- */

// โญ ็”จ `HasID` ๅ”ๅฎšไพ†็ตฑไธ€่ฆ็ฏ„้€™็จฎๆœ‰ใ€ŒID ๅฑฌๆ€งใ€็š„้กžๅˆฅใ€‚
// โญ ้€™็จฎๅšๆณ•็š„ๅฅฝ่™•ๆ˜ฏ๏ผšใ€ŒID ๅฑฌๆ€งใ€ไธ้œ€่ฆ็œŸ็š„ๅซ `id`๏ผŒๅซๅ…ถไป–ๅ็จฑไนŸๅฏไปฅใ€‚
protocol HasID {
    // โญ 2. ็”จ `IDType` ไพ†็จฑๅ‘ผๆญคใ€ŒID ๅฑฌๆ€งใ€็š„้กžๅˆฅ
    associatedtype IDType
    // โญ 1. ็”จ keypath ไพ†ๆŒ‡ๅฎšๅ“ชๅ€‹ๅฑฌๆ€งๆ˜ฏใ€ŒID ๅฑฌๆ€งใ€
    static var idKey: WritableKeyPath<Self, IDType> { get }
}

/* -------- protocol extension (default behaviors) -------- */

extension HasID {
    func printID(){
        print(self[keyPath: Self.idKey])
    }
}

/* -------- protocol conformances -------- */

extension Person: HasID {
    static let idKey = \Person.ssn  // โญ WritableKeyPath<Person, String>
}

extension Book: HasID {
    static let idKey = \Book.isbn   // โญ WritableKeyPath<Book, String>
}

/* -------- main -------- */

let taylor = Person(ssn: "555-55-5555", name: "Taylor Swift")
let book = Book(isbn: "1234-5678", title: "Snow White")

taylor.printID()    // 555-55-5555
book.printID()      // 1234-5678

print(type(of: Person.idKey))       // WritableKeyPath<Person, String>
print(type(of: Book.idKey))         // WritableKeyPath<Book, String>

Last updated