Swift Academy · Lektion

@dynamicMemberLookup

Erstellen Sie dynamischen, typsicheren Memberzugriff.

Lektion 4 von 413 Schritte

@dynamicMemberLookup ist eine kostenlose Swift Academy-Lektion auf CoddyKit. Dies ist Lektion 4 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.

Was ist Dynamic Member Lookup?

Das Attribut @dynamicMemberLookup ermöglicht es einem Typ, auf den Zugriff auf nicht deklarierte Member in Punktnotation zu reagieren. Wenn Sie value.something schreiben, leitet Swift den Zugriff an einen speziellen Subscript weiter, den Sie definieren.

Dadurch wirken Wrapper-Typen natürlich, während der Zugriff an einer zentralen Stelle bleibt.

@dynamicMemberLookup
struct Settings {
    private var storage: [String: String] = ["theme": "dark"]
    subscript(dynamicMember key: String) -> String? {
        storage[key]
    }
}

let s = Settings()
print(s.theme ?? "none")

Der erforderliche Subscript

Ein mit @dynamicMemberLookup markierter Typ muss subscript(dynamicMember:) implementieren. Wenn der Parameter ein String ist, wird der von Ihnen eingegebene Membername zur Laufzeit zu diesem String.

config.timeout ruft den Subscript daher mit dem Schlüssel "timeout" auf.

@dynamicMemberLookup
struct Config {
    let values: [String: Int]
    subscript(dynamicMember member: String) -> Int {
        values[member] ?? 0
    }
}

let config = Config(values: ["timeout": 30, "retries": 3])
print(config.timeout)
print(config.retries)

String-Suche ist nicht typsicher

Die dynamische Membersuche auf String-Basis ist flexibel, verliert aber die Überprüfung zur Compilezeit. Wenn Sie einen Membernamen falsch schreiben, wird der Code trotzdem kompiliert, und Sie erhalten das Ergebnis, das der Subscript für einen fehlenden Schlüssel zurückgibt.

Im folgenden Beispiel gibt ein unbekannter Member stillschweigend den Standardwert zurück, anstatt den Build fehlschlagen zu lassen.

@dynamicMemberLookup
struct Config {
    let values: [String: Int]
    subscript(dynamicMember member: String) -> Int {
        values[member] ?? -1
    }
}

let config = Config(values: ["timeout": 30])
print(config.tmout)

Typsichere Suche mit Key Paths

Für mehr Sicherheit können Sie den Subscript so gestalten, dass er statt eines Strings einen KeyPath entgegennimmt. Nun überprüft der Compiler, ob der Member im umschlossenen Typ vorhanden ist. Dadurch erhalten Sie wieder eine vollständige Überprüfung und können den Zugriff weiterhin weiterleiten.

Dieses Muster eignet sich ideal für Wrapper-Typen, die einen stark typisierten Wert enthalten.

struct User { let name: String; let age: Int }

@dynamicMemberLookup
struct Boxed {
    let user: User
    subscript<T>(dynamicMember path: KeyPath<User, T>) -> T {
        user[keyPath: path]
    }
}

let boxed = Boxed(user: User(name: "Ada", age: 36))
print(boxed.name)
print(boxed.age)

Warum die Key-Path-Variante sicherer ist

Da der Subscript einen KeyPath<User, T> entgegennimmt, sind nur tatsächlich in User vorhandene Member zulässig. Ein Tippfehler wie boxed.naem würde nun zu einem Compilerfehler führen, anders als bei der String-Variante.

Sie erhalten den Komfort der Punktnotation ohne dieses Risiko.

struct User { let name: String; let age: Int }

@dynamicMemberLookup
struct ReadOnly {
    let value: User
    subscript<T>(dynamicMember path: KeyPath<User, T>) -> T {
        value[keyPath: path]
    }
}

let r = ReadOnly(value: User(name: "Lin", age: 22))
print(r.name, r.age)

Schreibbare dynamische Member

Wenn der Subscript einen Setter bereitstellt und einen WritableKeyPath entgegennimmt, können Sie auch weitergeleiteten Membern Werte zuweisen. Der Wrapper leitet den Schreibzugriff direkt an den umschlossenen Wert weiter.

So entsteht ein transparenter, veränderbarer Wrapper.

struct Profile { var name: String; var score: Int }

@dynamicMemberLookup
struct Wrapper {
    var value: Profile
    subscript<T>(dynamicMember path: WritableKeyPath<Profile, T>) -> T {
        get { value[keyPath: path] }
        set { value[keyPath: path] = newValue }
    }
}

var w = Wrapper(value: Profile(name: "Mo", score: 0))
w.score = 99
print(w.value.score)

An ein umschlossenes Objekt weiterleiten

Dynamic Member Lookup eignet sich hervorragend für leichte Proxys, die hauptsächlich an einen inneren Wert weiterleiten, aber zusätzlich etwas Verhalten hinzufügen. Der Subscript hält die Weiterleitungslogik an einer zentralen Stelle.

Hier leitet ein Logging-Wrapper Lesezugriffe weiter und gibt aus, auf welchen Member zugegriffen wurde.

struct Account { let id: Int; let balance: Double }

@dynamicMemberLookup
struct Logged {
    let account: Account
    subscript<T>(dynamicMember path: KeyPath<Account, T>) -> T {
        let result = account[keyPath: path]
        print("accessed a member")
        return result
    }
}

let logged = Logged(account: Account(id: 7, balance: 100))
print(logged.balance)

Mit Konzepten für Dynamic Callable kombinieren

Dynamic Member Lookup lässt sich gut mit Generics kombinieren. Ein einziger generischer Subscript kann Eigenschaften beliebiger Typen weiterleiten, sodass ein Wrapper Werte verschiedenster Formen unterstützt.

Hier funktioniert derselbe Proxy unabhängig davon, ob der Member ein String oder ein Int ist.

struct Item { let title: String; let count: Int }

@dynamicMemberLookup
struct Proxy<Wrapped> {
    let wrapped: Wrapped
    subscript<T>(dynamicMember path: KeyPath<Wrapped, T>) -> T {
        wrapped[keyPath: path]
    }
}

let proxy = Proxy(wrapped: Item(title: "Book", count: 4))
print(proxy.title, proxy.count)

String-Suche für JSON-ähnliche Daten

Die String-Variante hat weiterhin ihre Berechtigung: Sie eignet sich für locker strukturierte Daten wie geparstes JSON, bei denen die Member zur Compilezeit nicht bekannt sind. Jeder Zugriff wird zu einer Dictionary-Suche.

Hier stellt ein kleiner JSON-ähnlicher Wert seine Felder über die Punktnotation bereit.

@dynamicMemberLookup
struct JSON {
    let fields: [String: String]
    subscript(dynamicMember key: String) -> String {
        fields[key] ?? ""
    }
}

let json = JSON(fields: ["city": "Oslo", "country": "Norway"])
print(json.city)
print(json.country)

Zu beachtende Einschränkungen

Dynamic Member Lookup beeinflusst nur die Syntax des Memberzugriffs; es fügt keine echten gespeicherten Eigenschaften hinzu. Entwicklungswerkzeuge wie die Autovervollständigung funktionieren bei der Key-Path-Variante, nicht jedoch bei beliebigen String-Schlüsseln.

Bevorzugen Sie die Key-Path-Variante, sobald die Struktur der zugrunde liegenden Daten bekannt ist, und reservieren Sie die String-Variante für tatsächlich dynamische Daten.

struct Point { let x: Int; let y: Int }

@dynamicMemberLookup
struct Safe {
    let point: Point
    subscript<T>(dynamicMember path: KeyPath<Point, T>) -> T {
        point[keyPath: path]
    }
}

let safe = Safe(point: Point(x: 3, y: 4))
print(safe.x + safe.y)

Ein praktischer Decorator

Zum Abschluss sehen Sie einen maßvollen Wrapper, der jeden Lesezugriff auf eine Eigenschaft an seinen inneren Wert weiterleitet und dabei die Zugriffe zählt. Reale Frameworks verwenden diese Idee für Beobachtung und Tracing.

Die Punktnotation des Wrappers fühlt sich genauso an wie die direkte Verwendung des Werts.

struct Sensor { let temperature: Double; let humidity: Double }

@dynamicMemberLookup
class Tracked {
    let sensor: Sensor
    var reads = 0
    init(_ s: Sensor) { sensor = s }
    subscript<T>(dynamicMember path: KeyPath<Sensor, T>) -> T {
        reads += 1
        return sensor[keyPath: path]
    }
}

let t = Tracked(Sensor(temperature: 21.5, humidity: 0.4))
print(t.temperature)
print(t.humidity)
print(t.reads)

Kurzer Test: Typsichere dynamische Suche

Rufen Sie sich in Erinnerung, welcher Subscript-Parameter die dynamische Membersuche typsicher macht.

Zusammenfassung: Dynamische Member-Suche

Sie haben gelernt, wie @dynamicMemberLookup funktioniert:

  • Das Attribut leitet nicht deklarierte Zugriffe in Punktnotation an subscript(dynamicMember:) weiter.
  • Ein String-Parameter ermöglicht flexiblen, aber nicht geprüften Zugriff – ideal für JSON-ähnliche Daten.
  • Ein KeyPath-Parameter stellt vollständige Typsicherheit und Autovervollständigung wieder her.
  • Mit einem WritableKeyPath und einem Setter können Sie Schreibzugriffe über einen Wrapper weiterleiten.
  • Es handelt sich um eine Syntax-Erleichterung, die sich besonders gut mit Proxy- und Decorator-Patterns kombinieren lässt.

Damit verfügen Sie jetzt über den vollständigen Werkzeugkasten für KeyPaths: Lesen, Schreiben, die Verwendung in Collections und dynamische Weiterleitung.

struct User { let name: String }

@dynamicMemberLookup
struct Wrap {
    let user: User
    subscript<T>(dynamicMember path: KeyPath<User, T>) -> T {
        user[keyPath: path]
    }
}

print(Wrap(user: User(name: "Final")).name)
Kostenlos starten

Lerne Swift mit einem KI-Tutor — kostenlos

Schreibe und führe echten Code in deinem Browser aus, bekomme sofortige Hilfe von einem 24/7 KI-Tutor und setze dein Lernen im Web oder in der App fort.

Kurse
122
Lektionen
409

Häufig gestellte Fragen

Ist die Lektion „@dynamicMemberLookup“ kostenlos?

Ja — der vollständige Text von „@dynamicMemberLookup“ 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 „@dynamicMemberLookup“?

Erstellen Sie dynamischen, typsicheren Memberzugriff. 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 4 von 4.

Wie lange dauert die Lektion „@dynamicMemberLookup“?

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