0Pricing
Swift Academy · Lezione

KeyPath scrivibili e di riferimento

Leggi e scrivi attraverso i key path.

KeyPath scrivibili e di riferimento è una lezione Swift Academy gratuita su CoddyKit. Questa è la lezione 3 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Swift Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Swift Academy include 4 lezioni in totale.

Key path di sola lettura e scrivibili

Un semplice KeyPath consente soltanto di leggere un valore. Per scrivere tramite un key path serve una variante scrivibile. Swift ne offre due: una per i tipi valore e una per i tipi riferimento.

In questa lezione vedrà WritableKeyPath per le struct e ReferenceWritableKeyPath per le classi, oltre a come il pedice [keyPath:] diventi scrivibile.

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

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

WritableKeyPath per i tipi valore

Un WritableKeyPath fa riferimento a una proprietà memorizzata modificabile di un tipo valore. Per impostare un valore tramite questo key path, anche l'istanza deve essere una var, perché modificare una proprietà di una struct modifica l'intero valore.

Usi il pedice [keyPath:] a sinistra di un'assegnazione per scrivere il valore.

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)

Perché l'istanza deve essere una var

Per i tipi valore, scrivere tramite un key path modifica una copia sul posto. Se l'istanza è una let, non c'è nulla da modificare, quindi l'assegnazione non verrà compilata.

La regola rispecchia la normale modifica di una proprietà: si può impostare una proprietà memorizzata di una struct solo quando la struct è contenuta in una variabile.

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)

Un helper generico per impostare i valori

Poiché un key path scrivibile specifica quale proprietà modificare, si può scrivere una funzione generica che aggiorna qualsiasi proprietà di qualsiasi tipo valore. Si passa l'istanza come inout in modo che la modifica venga riscritta nel valore originale.

Questa è la base di piccole utility per gli aggiornamenti funzionali.

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 per le classi

Per le classi, Swift fornisce ReferenceWritableKeyPath. Poiché un'istanza di classe è un riferimento, si può scrivere tramite essa anche quando l'istanza è contenuta in una costante let; il riferimento non cambia, cambia solo l'oggetto a cui punta.

Questa è la differenza fondamentale rispetto ai key path scrivibili dei tipi valore.

class Counter {
    var value: Int = 0
}

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

Riferimento let, oggetto modificabile

Noti che l'istanza della classe qui sotto è una let, eppure è ancora possibile impostare la sua proprietà tramite il key path. Con una struct si verificherebbe un errore di compilazione.

Questo perché modificare una proprietà di una classe non richiede che il riferimento sia modificabile, ma solo che lo sia la proprietà stessa.

class Profile {
    var nickname: String = ""
}

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

La gerarchia dei tipi di key path

I tipi di key path scrivibili formano una gerarchia. ReferenceWritableKeyPath è un sottotipo di WritableKeyPath, che a sua volta è un sottotipo di KeyPath. Pertanto, un key path più specifico può essere usato ovunque ne sia previsto uno più generale.

Questo significa che si può passare un ReferenceWritableKeyPath a una funzione che deve soltanto leggere tramite un 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))

Aggiornare tipi valore annidati

I key path scrivibili possono concatenarsi attraverso struct annidate. Impostare una proprietà profondamente annidata riscrive ogni valore contenitore lungo la catena, il tutto con una singola assegnazione.

Qui si modifica la città all'interno di un indirizzo annidato.

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)

Applicare più aggiornamenti

Poiché i key path scrivibili sono valori, si può memorizzare un elenco di aggiornamenti sotto forma di coppie key path-valore e applicarli in un ciclo. Si tratta di un piccolo sistema di patch.

Qui si applicano due modifiche a una struct delle impostazioni.

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)

Configurazione in stile binding

Un uso comune nel mondo reale consiste in un helper configure che imposta una proprietà su un oggetto appena creato e lo restituisce, consentendo uno stile fluido. Con le classi, questo funziona anche su un risultato let.

Qui si imposta il testo di un'etichetta tramite un key path scrivibile per riferimenti.

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)

Scegliere il tipo di key path corretto

Usi KeyPath quando deve solo leggere, WritableKeyPath per impostare una proprietà di un tipo valore memorizzato in una var e ReferenceWritableKeyPath per impostare una proprietà di una classe anche tramite una let.

Scegliere il tipo più specifico adatto mantiene le API coerenti con il fatto che leggano o modifichino i dati.

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))

Verifica rapida: key path scrivibili

Ricordi quale tipo di key path consente di impostare una proprietà di una classe anche quando l'istanza è una costante let.

Riepilogo: key path scrivibili e per riferimenti

Ha imparato a scrivere tramite i key path:

  • WritableKeyPath imposta una proprietà memorizzata di un tipo valore e richiede un'istanza var.
  • ReferenceWritableKeyPath imposta una proprietà di una classe e funziona anche tramite una let.
  • Il pedice [keyPath:] compare a sinistra di un'assegnazione per scrivere il valore.
  • I tipi formano una gerarchia, quindi un key path scrivibile può essere usato al posto di uno di sola lettura.
  • Gli setter generici inout e gli helper configure si basano su questi concetti.

Successivamente vedrà @dynamicMemberLookup, che usa i key path per offrire l'accesso con la sintassi a punto ai dati dinamici.

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)")

Domande Frequenti

La lezione «KeyPath scrivibili e di riferimento» è gratuita?

Sì — il testo completo di «KeyPath scrivibili e di riferimento» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Swift Academy, passa a CoddyKit PRO. Il corso Swift Academy include 4 lezioni in totale.

Cosa imparerò in «KeyPath scrivibili e di riferimento»?

Leggi e scrivi attraverso i key path. Eserciti Swift Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Swift Academy?

Non è richiesta alcuna esperienza precedente. Swift Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 4.

Quanto tempo richiede la lezione «KeyPath scrivibili e di riferimento»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Swift Academy?

Sì. Ogni lezione Swift Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Basi dei KeyPath
  2. Uso dei KeyPath nelle collezioni
  3. KeyPath scrivibili e di riferimento
  4. @dynamicMemberLookup
← Torna a Swift Academy