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:
WritableKeyPathustawia przechowywaną właściwość typu wartości, wymagając instancjivar.ReferenceWritableKeyPathustawia właściwość klasy i działa nawet za pośrednictwemlet.- 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
inoutoraz funkcjeconfigurekorzystają 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
- Podstawy KeyPath
- Używanie KeyPath w kolekcjach
- Zapisywalne i referencyjne KeyPath
- @dynamicMemberLookup