@dynamicMemberLookup
Construisez un accès dynamique et sûr du point de vue des types aux membres.
@dynamicMemberLookup est une leçon Swift Academy gratuite sur CoddyKit. Ceci est la leçon 4 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Swift Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Swift Academy comprend 4 leçons au total.
Qu'est-ce que la recherche dynamique de membres ?
L'attribut @dynamicMemberLookup permet à un type de répondre à un accès à un membre avec la notation pointée, même si ce membre n'est pas déclaré comme une véritable propriété. Lorsque vous écrivez value.something, Swift l'achemine vers un sous-script spécial que vous définissez.
Les types enveloppes acquièrent ainsi une apparence naturelle, tout en centralisant l'accès en un seul endroit.
@dynamicMemberLookup
struct Settings {
private var storage: [String: String] = ["theme": "dark"]
subscript(dynamicMember key: String) -> String? {
storage[key]
}
}
let s = Settings()
print(s.theme ?? "none")Le sous-script requis
Un type marqué @dynamicMemberLookup doit implémenter subscript(dynamicMember:). Lorsque le paramètre est un String, le nom du membre que vous saisissez devient cette chaîne au moment de l'exécution.
Ainsi, config.timeout appelle le sous-script avec la clé "timeout".
@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)La recherche par chaîne n'est pas sûre du point de vue des types
La recherche dynamique de membres fondée sur des chaînes est flexible, mais elle perd la vérification à la compilation. Si vous faites une faute dans le nom d'un membre, le code compile tout de même et vous obtenez ce que le sous-script renvoie pour une clé absente.
Ci-dessous, un membre inconnu renvoie discrètement la valeur par défaut au lieu d'empêcher la compilation.
@dynamicMemberLookup
struct Config {
let values: [String: Int]
subscript(dynamicMember member: String) -> Int {
values[member] ?? -1
}
}
let config = Config(values: ["timeout": 30])
print(config.tmout)Une recherche sûre grâce aux chemins de clés
Pour renforcer la sécurité, vous pouvez faire accepter au sous-script un KeyPath plutôt qu'une chaîne. Le compilateur vérifie alors que le membre existe sur le type enveloppé, ce qui rétablit une vérification complète tout en continuant à transmettre l'accès.
Ce schéma convient parfaitement aux types enveloppes qui contiennent une donnée fortement typée.
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)Pourquoi la version avec chemin de clé est plus sûre
Comme le sous-script accepte un KeyPath<User, T>, seuls les membres qui existent réellement sur User sont autorisés. Une faute telle que boxed.naem empêcherait désormais la compilation, contrairement à la version fondée sur une chaîne.
Vous bénéficiez de la facilité de la notation pointée sans aucun de ces risques.
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)Membres dynamiques accessibles en écriture
Si le sous-script fournit un accesseur d'écriture et accepte un WritableKeyPath, vous pouvez également affecter des valeurs aux membres transmis. L'enveloppe transmet directement l'écriture à la donnée enveloppée.
Vous obtenez ainsi une enveloppe mutable transparente.
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)Transmettre les accès à un objet enveloppé
La recherche dynamique de membres est idéale pour les proxys légers qui transmettent principalement les accès à une donnée interne tout en ajoutant un peu de comportement. Le sous-script centralise la logique de transmission.
Ici, une enveloppe de journalisation transmet les lectures et affiche le membre auquel on a accédé.
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)Associer cette approche aux fonctions dynamiques appelables
La recherche dynamique de membres s'associe bien aux génériques. Un seul sous-script générique peut transmettre n'importe quel type de propriété, de sorte qu'une même enveloppe fonctionne avec des données de formes variées.
Ici, le même Proxy fonctionne que le membre soit un String ou un Int.
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)La recherche par chaîne pour des données de type JSON
La forme fondée sur les chaînes reste utile pour représenter des données peu structurées, comme du JSON analysé, dont les membres ne sont pas connus à la compilation. Chaque accès devient une recherche dans un dictionnaire.
Ici, une petite donnée de type JSON expose ses fields avec la notation pointée.
@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)Limites à garder à l'esprit
La recherche dynamique de membres ne concerne que la syntaxe d'accès aux membres ; elle n'ajoute pas de véritables propriétés stockées. Les outils comme l'autocomplétion fonctionnent avec la forme fondée sur les chemins de clés, mais pas avec des clés textuelles arbitraires.
Privilégiez la version avec chemin de clé lorsque la structure sous-jacente est connue, et réservez la version fondée sur les chaînes aux données réellement dynamiques.
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)Un décorateur pratique
En réunissant ces éléments, voici une enveloppe instrumentée qui transmet la lecture de chaque propriété à sa donnée interne tout en comptant les accès. Les véritables infrastructures utilisent cette idée pour l'observation et le traçage.
La notation pointée de l'enveloppe semble identique à l'utilisation directe de la donnée.
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)Vérification rapide : recherche dynamique sûre du point de vue des types
Rappelez-vous quel paramètre du sous-script rend la recherche dynamique de membres sûre du point de vue des types.
Récapitulatif : recherche dynamique de membres
Vous avez appris comment fonctionne @dynamicMemberLookup :
- L’attribut redirige l’accès non déclaré avec la syntaxe à points vers
subscript(dynamicMember:). - Un paramètre
Stringoffre un accès flexible mais non vérifié, idéal pour les données de type JSON. - Un paramètre
KeyPathrétablit la sécurité complète des types et la complétion automatique. - Un
WritableKeyPathdoté d’un modificateur permet de transférer les écritures à travers une enveloppe. - Il s’agit d’une commodité syntaxique qui s’associe naturellement aux motifs de mandataire et de décorateur.
Vous disposez maintenant de toute la boîte à outils des chemins de clés : lecture, écriture, utilisation avec des collections et transfert dynamique.
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)Questions Fréquemment Posées
La leçon « @dynamicMemberLookup » est-elle gratuite ?
Oui — le texte complet de « @dynamicMemberLookup » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Swift Academy, passe à CoddyKit PRO. Le cours Swift Academy comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « @dynamicMemberLookup » ?
Construisez un accès dynamique et sûr du point de vue des types aux membres. Tu pratiques Swift Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer Swift Academy ?
Aucune expérience préalable n'est requise. Swift Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 4 sur 4.
Combien de temps prend la leçon « @dynamicMemberLookup » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon Swift Academy ?
Oui. Chaque leçon Swift Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- Bases de KeyPath
- Utiliser KeyPaths dans les collections
- KeyPaths accessibles en écriture et de référence
- @dynamicMemberLookup