Historia pytania:
Optional chaining pojawiło się w Swift, aby ułatwić pracę z zagnieżdżonymi optionalami, pozwalając na pisanie zwartego i bezpiecznego kodu bez niekończących się sprawdzeń na nil. Jest to szczególnie przydatne przy odwoływaniu się do właściwości i metod obiektów, które mogą być nieobecne.
Problem:
Pracując z optional chaining, łatwo źle zrozumieć, jaki rezultat uzyskamy, jeśli jeden z obiektów w łańcuchu będzie równy nil, lub jeśli niepoprawnie przetworzymy zwracane wartości, możemy napotkać błędy wykonania lub nieoczekiwane zachowanie.
Rozwiązanie:
Optional chaining to mechanizm, który pozwala bezpiecznie uzyskiwać dostęp do zagnieżdżonych właściwości, metod i subskrypcji obiektów, które mogą być nil. Jeśli jakikolwiek element w łańcuchu jest równy nil, cały wyraz zwraca nil, nie wywołując błędu.
Przykład kodu:
class Address { var city: String? } class User { var address: Address? } let user: User? = User() user?.address?.city = "Moskwa" if let city = user?.address?.city { print(city) } else { print("Miasto nie znalezione") }
Kluczowe cechy:
Czy występuje błąd wykonania, gdy próbujesz wywołać metodę lub uzyskać właściwość przez optional chaining, jeśli obiekt jest równy nil?
Nie, błąd wykonania nie występuje. Całe wyrażenie przez optional chaining zwraca nil, wykonanie przerywa się bez błędu.
Przykład kodu:
let email: String? = nil let lowercased = email?.lowercased() // lowercased będzie nil, błąd nie wystąpi
Czy przypisanie przez optional chaining będzie wykonywane, jeśli obiekt pośredni jest nieobecny?
Nie, jeśli obiekt lub pośrednia właściwość jest nil, przypisanie nie wywoła żadnych efektów i nie zmieni pamięci.
Przykład kodu:
var user: User? = nil user?.address?.city = "Kazań" // nic się nie wydarzy, user — nil
Czy wynik optional chaining może być nie optional?
Nie, wynik dowolnego wyrażenia przez optional chaining jest zawsze optional, nawet jeśli pierwotna właściwość nie jest opcjonalna.
Przykład kodu:
class Test { var number: Int = 10 } let t: Test? = nil let value = t?.number // value: Int? (optional)
W kodzie uzyskuje się dostęp do user?.address?.city bez późniejszej weryfikacji obecności miasta i od razu wywołuje city!. Powoduje to awarię, jeśli choćby jeden element jest nil.
Zalety:
Wady:
W kodzie używa się if let lub guard let do sprawdzenia user?.address?.city i dopiero potem pracują ze wartością.
Zalety:
Wady: