Skrivbare og referencebaserede KeyPaths
Læs og skriv via key paths.
Skrivbare og referencebaserede KeyPaths er en gratis Swift Academy-lektion på CoddyKit. Dette er lektion 3 af 4. Du kan læse alle 3 lektioner i dette læringsspor gratis i deres fulde længde — derefter låser CoddyKit PRO alle lektioner op samt praktiske øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Den er en del af læringsforløbet i Swift Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Swift Academy-kurset indeholder 4 lektioner i alt.
Skrivebeskyttede og skrivbare key paths
En almindelig KeyPath kan kun læse en værdi. Hvis du vil skrive via en key path, skal du bruge en skrivbar variant. Swift har to af dem: én til værdityper og én til referencetyper.
Denne lektion handler om WritableKeyPath til structs og ReferenceWritableKeyPath til klasser samt om, hvordan subscriptet [keyPath:] bliver skrivbart.
struct Person {
var name: String
var age: Int
}
let writable: WritableKeyPath<Person, Int> = \Person.age
print(type(of: writable))WritableKeyPath til værdityper
En WritableKeyPath peger på en lagret egenskab, der kan ændres, i en værditype. Hvis du vil sætte en værdi via den, skal selve instansen være en var, fordi ændring af en struct-egenskab ændrer hele værdien.
Brug subscriptet [keyPath:] på venstre side af en tildeling for at skrive en værdi.
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)Hvorfor instansen skal være en var
For værdityper ændrer skrivning via en key path en kopi på stedet. Hvis instansen er en let, er der ikke noget, der kan ændres, så tildelingen kan ikke kompileres.
Reglen svarer til normal ændring af egenskaber: Du kan kun sætte en structs lagrede egenskab, når structen ligger i en variabel.
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)En generisk sætterhjælpefunktion
Fordi en skrivbar key path indeholder oplysninger om, hvilken egenskab der skal ændres, kan du skrive en generisk funktion, der opdaterer alle egenskaber i alle værdityper. Send instansen som inout, så ændringen skrives tilbage.
Dette er grundlaget for små hjælpefunktioner til funktionelle opdateringer.
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 til klasser
Til klasser leverer Swift ReferenceWritableKeyPath. Fordi en klasseinstans er en reference, kan du skrive via den, selv når instansen ligger i en let-konstant; referencen ændres ikke, kun det objekt, den peger på.
Det er den vigtigste forskel fra skrivbare key paths til værdityper.
class Counter {
var value: Int = 0
}
let counter = Counter()
let path: ReferenceWritableKeyPath<Counter, Int> = \Counter.value
counter[keyPath: path] = 5
print(counter.value)En let-reference og et foranderligt objekt
Bemærk, at klasseinstansen nedenfor er en let, og alligevel kan vi sætte dens egenskab via key pathen. Med en struct ville dette være en kompileringsfejl.
Det skyldes, at ændring af en klasseegenskab ikke kræver, at referencen kan ændres, kun at selve egenskaben kan ændres.
class Profile {
var nickname: String = ""
}
let profile = Profile()
let nickPath = \Profile.nickname
profile[keyPath: nickPath] = "Ace"
print(profile.nickname)Key paths' typehierarki
De skrivbare key path-typer danner et hierarki. ReferenceWritableKeyPath er en undertype af WritableKeyPath, som er en undertype af KeyPath. Derfor kan en mere specifik key path bruges alle steder, hvor der forventes en mere generel.
Det betyder, at du kan sende en ReferenceWritableKeyPath til en funktion, der kun har brug for at læse via en KeyPath.
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))Opdatering af indlejrede værdityper
Skrivbare key paths kan kædes gennem indlejrede structs. Når du sætter en dybt indlejret egenskab, omskrives hver omsluttende værdi op gennem kæden i én enkelt tildeling.
Her ændrer vi byen inde i en indlejret 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)Anvendelse af flere opdateringer
Fordi skrivbare key paths er værdier, kan du gemme en liste over opdateringer som par af key paths og værdier og anvende dem i en løkke. Det er et lille rettelsessystem.
Her anvender vi to ændringer på en settings-struct.
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 i bindingsstil
En almindelig anvendelse i praksis er en configure-hjælpefunktion, der sætter en egenskab på et nyoprettet objekt og returnerer det, så du kan bruge en kædbar stil. Med klasser fungerer dette på et resultat, der ligger i en let.
Her sætter vi teksten i en etiket via en skrivbar key path til en reference.
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)Valg af den rigtige key path-type
Brug KeyPath, når du kun læser, WritableKeyPath til at sætte en egenskab på en værditype, der ligger i en var, og ReferenceWritableKeyPath til at sætte en egenskab på en klasse, selv gennem en let.
Ved at vælge den mest specifikke type, der passer, gør du dine API'er tydelige om, hvorvidt de læser eller ændrer data.
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))Hurtigt tjek: Skrivbare key paths
Husk, hvilken key path-type der lader dig sætte en klasseegenskab, selv når instansen er en let-konstant.
Opsummering: Skrivbare key paths og reference-key paths
Du har lært, hvordan du skriver via key paths:
WritableKeyPathsætter en lagret egenskab på en værditype og kræver envar-instans.ReferenceWritableKeyPathsætter en egenskab på en klasse og fungerer også gennem enlet.- Subscriptet
[keyPath:]står på venstre side af en tildeling, når du vil skrive en værdi. - Typerne danner et hierarki, så en skrivbar key path kan bruges i stedet for en skrivebeskyttet.
- Generiske
inout-sættere og configure-hjælpefunktioner bygger videre på dette.
Dernæst skal du se @dynamicMemberLookup, som bruger key paths til at tilbyde adgang til dynamiske data via punktnotation.
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)")Lær Swift med en AI-underviser — gratis
Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.
- Kurser
- 122
- Lektioner
- 409
Ofte stillede spørgsmål
Er lektionen “Skrivbare og referencebaserede KeyPaths” gratis?
Ja — alle 3 lektioner i læringssporet Swift Academy, inklusive “Skrivbare og referencebaserede KeyPaths”, kan læses gratis i deres fulde længde her på webstedet. Derefter låser CoddyKit PRO alle lektioner op samt interaktive øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Swift Academy-kurset indeholder 4 lektioner i alt.
Hvad lærer jeg i “Skrivbare og referencebaserede KeyPaths”?
Læs og skriv via key paths. Du øver dig i Swift Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.
Skal jeg have erfaring for at begynde på Swift Academy?
Der kræves ingen tidligere erfaring. Swift Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 3 af 4.
Hvor lang tid tager lektionen “Skrivbare og referencebaserede KeyPaths”?
De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.
Kan jeg skrive og køre kode i denne Swift Academy-lektion?
Ja. Alle Swift Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.
Alle lektioner i dette kursus
- Grundlæggende KeyPath
- Brug af KeyPaths i collections
- Skrivbare og referencebaserede KeyPaths
- @dynamicMemberLookup