0Pricing
Swift Academy · Lekcja

Zapisywalne i referencyjne KeyPath

Odczytywanie i zapisywanie za pomocą ścieżek kluczy.

Zapisywalne i referencyjne KeyPath to bezpłatna lekcja Swift Academy na CoddyKit. To lekcja 3 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Swift Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Swift Academy zawiera 4 lekcji w sumie.

Ścieżki kluczy tylko do odczytu i zapisywalne

Zwykła ścieżka KeyPath pozwala tylko odczytać wartość. Aby zapisywać za pomocą ścieżki klucza, potrzebny jest jej zapisywalny wariant. Swift ma dwa takie warianty: jeden dla typów wartości, a drugi dla typów referencyjnych.

W tej lekcji omówiono WritableKeyPath dla struktur i ReferenceWritableKeyPath dla klas, a także to, jak indeks dolny [keyPath:] staje się zapisywalny.

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

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

<code>WritableKeyPath</code> dla typów wartości

Obiekt typu WritableKeyPath wskazuje zmienną właściwość przechowywaną w typie wartości. Aby zapisywać za jego pomocą, sama instancja musi być zadeklarowana jako var, ponieważ modyfikacja właściwości struktury modyfikuje całą wartość.

Użyj indeksu dolnego [keyPath:] po lewej stronie przypisania, aby zapisać wartość.

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)

Dlaczego instancja musi być zadeklarowana jako var

W przypadku typów wartości zapis za pomocą ścieżki klucza modyfikuje kopię w miejscu. Jeśli instancja jest zadeklarowana jako let, nie ma niczego, co można zmodyfikować, dlatego przypisanie się nie skompiluje.

Ta zasada odpowiada zwykłej modyfikacji właściwości: przechowywaną właściwość struktury można ustawić tylko wtedy, gdy struktura jest przechowywana w zmiennej.

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)

Generyczna funkcja pomocnicza do ustawiania wartości

Ponieważ zapisywalna ścieżka klucza określa, którą właściwość należy zmienić, można napisać generyczną funkcję aktualizującą dowolną właściwość dowolnego typu wartości. Instancję należy przekazać jako inout, aby zmiana została zapisana z powrotem.

To podstawa niewielkich narzędzi do aktualizacji funkcyjnych.

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)

<code>ReferenceWritableKeyPath</code> dla klas

W przypadku klas Swift udostępnia typ ReferenceWritableKeyPath. Ponieważ instancja klasy jest referencją, można zapisywać za jej pośrednictwem nawet wtedy, gdy instancja jest przechowywana w stałej let; sama referencja się nie zmienia, zmienia się tylko wskazywany przez nią obiekt.

To kluczowa różnica w porównaniu z zapisywalnymi ścieżkami kluczy dla typów wartości.

class Counter {
    var value: Int = 0
}

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

Referencja let, zmienny obiekt

Zauważ, że poniższa instancja klasy jest zadeklarowana jako let, a mimo to można ustawić jej właściwość za pomocą ścieżki klucza. W przypadku struktury spowodowałoby to błąd kompilacji.

Dzieje się tak, ponieważ modyfikacja właściwości klasy nie wymaga, aby referencja była zmienna — zmienna musi być tylko sama właściwość.

class Profile {
    var nickname: String = ""
}

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

Hierarchia typów ścieżek kluczy

Typy zapisywalnych ścieżek kluczy tworzą hierarchię. ReferenceWritableKeyPath jest podtypem WritableKeyPath, a ten jest podtypem KeyPath. Bardziej szczegółowej ścieżki klucza można więc użyć wszędzie tam, gdzie oczekiwana jest bardziej ogólna.

Oznacza to, że można przekazać ReferenceWritableKeyPath do funkcji, która potrzebuje tylko odczytu za pomocą 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))

Aktualizowanie zagnieżdżonych typów wartości

Zapisywalne ścieżki kluczy można łączyć w łańcuchy przechodzące przez zagnieżdżone struktury. Ustawienie głęboko zagnieżdżonej właściwości przepisuje każdą otaczającą wartość w całym łańcuchu — wszystko w ramach jednego przypisania.

Tutaj zmieniamy miasto wewnątrz zagnieżdżonego adresu.

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)

Stosowanie wielu aktualizacji

Ponieważ zapisywalne ścieżki kluczy są wartościami, można przechowywać listę aktualizacji w postaci par ścieżka klucza–wartość i stosować je w pętli. To niewielki system poprawek.

Tutaj stosujemy dwie zmiany do struktury ustawień.

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)

Konfiguracja w stylu wiązania

Częstym zastosowaniem w praktyce jest pomocnicza funkcja configure, która ustawia właściwość świeżo utworzonego obiektu i go zwraca, umożliwiając płynny styl konfiguracji. W przypadku klas działa to także z wynikiem przechowywanym w let.

Tutaj ustawiamy tekst etykiety za pomocą zapisywalnej ścieżki klucza dla referencji.

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)

Wybór odpowiedniego typu ścieżki klucza

Użyj KeyPath, gdy tylko odczytujesz wartość, WritableKeyPath, aby ustawiać właściwość typu wartości przechowywanego w var, oraz ReferenceWritableKeyPath, aby ustawiać właściwość klasy, nawet za pośrednictwem let.

Wybór najbardziej szczegółowego pasującego typu sprawia, że interfejsy API jasno określają, czy tylko odczytują, czy także modyfikują dane.

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

Szybkie sprawdzenie: zapisywalne ścieżki kluczy

Przypomnij sobie, który typ ścieżki klucza pozwala ustawić właściwość klasy nawet wtedy, gdy instancja jest stałą let.

Podsumowanie: zapisywalne ścieżki kluczy i ścieżki dla referencji

Dowiedziano się, jak zapisywać za pomocą ścieżek kluczy:

  • WritableKeyPath ustawia przechowywaną właściwość typu wartości, wymagając instancji var.
  • ReferenceWritableKeyPath ustawia właściwość klasy i działa nawet za pośrednictwem let.
  • Indeks dolny [keyPath:] pojawia się po lewej stronie przypisania, aby zapisać wartość.
  • Typy tworzą hierarchię, dlatego zapisywalna ścieżka klucza może zastępować ścieżkę tylko do odczytu.
  • Generyczne funkcje ustawiające z inout oraz funkcje configure korzystają z tych możliwości.

W następnej części poznasz @dynamicMemberLookup, które używa ścieżek kluczy do udostępniania dostępu do dynamicznych danych za pomocą składni kropkowej.

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

Często zadawane pytania

Czy lekcja „Zapisywalne i referencyjne KeyPath” jest bezpłatna?

Tak — pełny tekst „Zapisywalne i referencyjne KeyPath” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Swift Academy, przejdź na CoddyKit PRO. Kurs Swift Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Zapisywalne i referencyjne KeyPath”?

Odczytywanie i zapisywanie za pomocą ścieżek kluczy. Ćwiczysz Swift Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Swift Academy?

Nie wymagamy żadnego doświadczenia. Swift Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 3 z 4.

Ile czasu zajmuje lekcja „Zapisywalne i referencyjne KeyPath”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Swift Academy?

Tak. Każda lekcja Swift Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Podstawy KeyPath
  2. Używanie KeyPath w kolekcjach
  3. Zapisywalne i referencyjne KeyPath
  4. @dynamicMemberLookup
← Powrót do Swift Academy