0Pricing
Swift Academy · Lektion

Schreibbare und Referenz-KeyPaths

Lesen und schreiben Sie über KeyPaths.

Schreibbare und Referenz-KeyPaths ist eine kostenlose Swift Academy-Lektion auf CoddyKit. Dies ist Lektion 3 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Swift Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Swift Academy-Kurs umfasst insgesamt 4 Lektionen.

Lesbare und schreibbare Key Paths

Ein einfacher KeyPath kann einen Wert nur lesen. Um über einen Key Path zu schreiben, benötigen Sie eine schreibbare Variante. Swift stellt davon zwei bereit: eine für Werttypen und eine für Referenztypen.

In dieser Lektion geht es um WritableKeyPath für Structs und ReferenceWritableKeyPath für Klassen sowie darum, wie der Subscript [keyPath:] beschreibbar wird.

struct Person {
    var name: String
    var age: Int
}

let writable: WritableKeyPath<Person, Int> = \Person.age
print(type(of: writable))

WritableKeyPath für Werttypen

Ein WritableKeyPath verweist auf eine veränderbare gespeicherte Eigenschaft eines Werttyps. Um darüber einen Wert zu setzen, muss die Instanz selbst ein var sein, da das Ändern einer Struct-Eigenschaft den gesamten Wert verändert.

Verwenden Sie den Subscript [keyPath:] auf der linken Seite einer Zuweisung, um zu schreiben.

struct Person {
    var name: String
    var age: Int
}

var alice = Person(name: "Alice", age: 30)
let agePath = \Person.age
alice[keyPath: agePath] = 31
print(alice.age)

Warum die Instanz ein var sein muss

Bei Werttypen verändert das Schreiben über einen Key Path eine Kopie direkt an Ort und Stelle. Wenn die Instanz ein let ist, gibt es nichts zu verändern, daher lässt sich die Zuweisung nicht kompilieren.

Diese Regel entspricht der normalen Änderung einer Eigenschaft: Sie können die gespeicherte Eigenschaft eines Structs nur setzen, wenn das Struct in einer Variable gespeichert ist.

struct Point {
    var x: Int
    var y: Int
}

var p = Point(x: 1, y: 2)
p[keyPath: \Point.x] = 10
p[keyPath: \Point.y] = 20
print(p)

Ein generischer Setter-Helfer

Da ein schreibbarer Key Path festlegt, welche Eigenschaft geändert werden soll, können Sie eine generische Funktion schreiben, die jede Eigenschaft jedes Werttyps aktualisiert. Übergeben Sie die Instanz als inout, damit die Änderung zurückgeschrieben wird.

Dies bildet die Grundlage für kleine Hilfsfunktionen zur funktionalen Aktualisierung.

func update<Root, Value>(_ root: inout Root, _ path: WritableKeyPath<Root, Value>, to value: Value) {
    root[keyPath: path] = value
}

struct Person { var name: String; var age: Int }
var bob = Person(name: "Bob", age: 40)
update(&bob, \.age, to: 41)
print(bob.age)

ReferenceWritableKeyPath für Klassen

Für Klassen stellt Swift ReferenceWritableKeyPath bereit. Da eine Klasseninstanz eine Referenz ist, können Sie über sie schreiben, selbst wenn die Instanz in einer let-Konstanten gespeichert ist. Die Referenz ändert sich nicht, sondern nur das Objekt, auf das sie verweist.

Das ist der entscheidende Unterschied zu schreibbaren Key Paths von Werttypen.

class Counter {
    var value: Int = 0
}

let counter = Counter()
let path: ReferenceWritableKeyPath<Counter, Int> = \Counter.value
counter[keyPath: path] = 5
print(counter.value)

Eine let-Referenz, ein veränderbares Objekt

Beachten Sie, dass die folgende Klasseninstanz ein let ist und wir ihre Eigenschaft dennoch über den Key Path setzen können. Bei einem Struct würde dies zu einem Compilerfehler führen.

Der Grund ist, dass zum Ändern einer Klasseneigenschaft die Referenz selbst nicht veränderbar sein muss, sondern nur die Eigenschaft.

class Profile {
    var nickname: String = ""
}

let profile = Profile()
let nickPath = \Profile.nickname
profile[keyPath: nickPath] = "Ace"
print(profile.nickname)

Die Typhierarchie der Key Paths

Die Typen der schreibbaren Key Paths bilden eine Hierarchie. ReferenceWritableKeyPath ist ein Subtyp von WritableKeyPath, und dieses wiederum ist ein Subtyp von KeyPath. Daher kann ein spezifischerer Key Path überall dort verwendet werden, wo ein allgemeinerer erwartet wird.

Das bedeutet, dass Sie einen ReferenceWritableKeyPath an eine Funktion übergeben können, die über einen KeyPath lediglich lesen muss.

class Box { var size: Int = 1 }

func readSize(_ box: Box, _ path: KeyPath<Box, Int>) -> Int {
    box[keyPath: path]
}

let writable: ReferenceWritableKeyPath<Box, Int> = \Box.size
print(readSize(Box(), writable))

Verschachtelte Werttypen aktualisieren

Schreibbare Key Paths lassen sich durch verschachtelte Structs verketten. Beim Setzen einer tief verschachtelten Eigenschaft wird jeder umschließende Wert entlang der Kette in einer einzigen Zuweisung neu geschrieben.

Hier ändern wir die Stadt innerhalb einer verschachtelten Adresse.

struct Address { var city: String }
struct Person { var name: String; var address: Address }

var carol = Person(name: "Carol", address: Address(city: "Oslo"))
carol[keyPath: \Person.address.city] = "Bergen"
print(carol.address.city)

Viele Aktualisierungen anwenden

Da schreibbare Key Paths Werte sind, können Sie eine Liste von Aktualisierungen als Paare aus Key Path und Wert speichern und sie in einer Schleife anwenden. Das ist ein winziges Patch-System.

Hier wenden wir zwei Änderungen auf ein Settings-Struct an.

struct Settings { var volume: Int; var brightness: Int }

var settings = Settings(volume: 5, brightness: 5)
func apply(_ s: inout Settings, _ path: WritableKeyPath<Settings, Int>, _ v: Int) {
    s[keyPath: path] = v
}
apply(&settings, \.volume, 8)
apply(&settings, \.brightness, 3)
print(settings)

Konfiguration im Binding-Stil

Ein typischer praktischer Anwendungsfall ist ein configure-Helfer, der eine Eigenschaft eines neu erstellten Objekts setzt und es anschließend zurückgibt, sodass eine Fluent-Syntax möglich wird. Bei Klassen funktioniert dies auch mit einem let-Ergebnis.

Hier setzen wir den Text eines Labels über einen schreibbaren Referenz-Key-Path.

class Label { var text: String = "" }

func configure<T: AnyObject, V>(_ object: T, _ path: ReferenceWritableKeyPath<T, V>, _ value: V) -> T {
    object[keyPath: path] = value
    return object
}

let label = configure(Label(), \.text, "Hello")
print(label.text)

Den richtigen Key-Path-Typ wählen

Verwenden Sie KeyPath, wenn Sie nur lesen, WritableKeyPath, um eine Eigenschaft eines Werttyps zu setzen, der in einem var gespeichert ist, und ReferenceWritableKeyPath, um eine Eigenschaft einer Klasse auch über ein let zu setzen.

Wenn Sie den spezifischsten passenden Typ wählen, machen Sie in Ihren APIs deutlich, ob sie lesen oder verändern.

struct S { var n: Int }
class C { var n: Int = 0 }

let read: KeyPath<S, Int> = \S.n
let writeStruct: WritableKeyPath<S, Int> = \S.n
let writeClass: ReferenceWritableKeyPath<C, Int> = \C.n
print(type(of: read), type(of: writeStruct), type(of: writeClass))

Kurzer Test: Schreibbare Key Paths

Rufen Sie sich in Erinnerung, welcher Key-Path-Typ das Setzen einer Klasseneigenschaft ermöglicht, selbst wenn die Instanz eine let-Konstante ist.

Zusammenfassung: Schreibbare und Referenz-Key-Paths

Sie haben gelernt, wie Sie über Key Paths schreiben:

  • WritableKeyPath setzt eine gespeicherte Eigenschaft eines Werttyps und erfordert eine var-Instanz.
  • ReferenceWritableKeyPath setzt eine Eigenschaft einer Klasse und funktioniert auch über ein let.
  • Der Subscript [keyPath:] steht beim Schreiben auf der linken Seite einer Zuweisung.
  • Die Typen bilden eine Hierarchie, daher kann ein schreibbarer Key Path anstelle eines nur lesbaren verwendet werden.
  • Generische inout-Setter und configure-Helfer bauen darauf auf.

Als Nächstes sehen Sie @dynamicMemberLookup, das mithilfe von Key Paths den Zugriff auf dynamische Daten in Punktnotation ermöglicht.

struct Person { var name: String; var age: Int }

var dave = Person(name: "Dave", age: 27)
dave[keyPath: \Person.age] = 28
print("Updated age: \(dave.age)")

Häufig gestellte Fragen

Ist die Lektion „Schreibbare und Referenz-KeyPaths“ kostenlos?

Ja — der vollständige Text von „Schreibbare und Referenz-KeyPaths“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Swift Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Swift Academy-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „Schreibbare und Referenz-KeyPaths“?

Lesen und schreiben Sie über KeyPaths. Du übst Swift Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um Swift Academy zu starten?

Keine Vorkenntnisse erforderlich. Swift Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 3 von 4.

Wie lange dauert die Lektion „Schreibbare und Referenz-KeyPaths“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser Swift Academy-Lektion Code schreiben und ausführen?

Ja. Jede Swift Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. Grundlagen von KeyPaths
  2. KeyPaths in Collections verwenden
  3. Schreibbare und Referenz-KeyPaths
  4. @dynamicMemberLookup
← Zurück zu Swift Academy