programowanieiOS developer

Jak działają właściwości z obserwatorami (property observers) w Swift i po co są potrzebne?

Zdaj rozmowy kwalifikacyjne z asystentem AI Hintsage

Odpowiedź.

Właściwości z obserwatorami (property observers) w Swift pozwalają reagować na zmiany wartości właściwości. Ta koncepcja pojawiła się razem z Swift dla zwiększenia przejrzystości kontroli nad zmianami danych i automatyzacji logiki podczas zmian.

Historia pytania:

Przed Swift podobne zachowanie często było realizowane ręcznie przez setter'y lub specjalne metody. W Swift obserwatory pojawiły się jako standardowe narzędzie w języku.

Problem:

Programista musi być w stanie przechwycić moment zmiany właściwości — na przykład, aby zaktualizować UI lub zwalidować dane. Bez obserwatorów kod stawałby się bardziej rozbudowany i mniej czytelny.

Rozwiązanie:

W Swift dostępne są dwa podstawowe obserwatory:

  • willSet jest wywoływany przed zmianą wartości
  • didSet jest wywoływany po przypisaniu nowej wartości

Obserwatory można dodać do przechowywanych właściwości, z wyjątkiem właściwości leniwych i obliczanych (computed) właściwości.

Przykład kodu:

class Temperature { var celsius: Double { willSet { print("Wkrótce ustawi się wartość", newValue) } didSet { print("Wartość była:", oldValue, ", a stała się:", celsius) } } init(celsius: Double) { self.celsius = celsius } } let temp = Temperature(celsius: 22) temp.celsius = 28 // Wywoła willSet i didSet

Kluczowe cechy:

  • W obserwatorze willSet dostępna jest specjalna zmienna newValue
  • W didSet — oldValue
  • Obserwatory nie są wywoływane podczas inicjalizacji właściwości w init

Pytania z podstępem.

Czy można dodać obserwatory do obliczanych (computed) właściwości?

Nie, do obliczanych właściwości nie można dodać willSet i didSet, ponieważ mają już własne gettery i settery. Użycie willSet/didSet jest aktualne tylko dla przechowywanych właściwości.

Czy obserwatory zostaną wywołane podczas zmiany właściwości wewnątrz inicjalizatora?

Nie, obserwatory właściwości nie są wywoływane podczas inicjalizacji (init). Działają tylko przy zmianie wartości po zakończeniu init.

Co się stanie, gdy przypiszesz bieżącą wartość samej sobie, na przykład x = x?

Obserwatory i tak zostaną wywołane, nawet jeśli wartość właściwości się nie zmieniła! Może to prowadzić do ubocznego wykonania logiki — bądź ostrożny.

var value: Int = 0 { didSet { print("didSet zawsze się wywołuje!") } } value = value // didSet się wywoła

Typowe błędy i antywzorce

  • Zależność od efektów ubocznych: realizacja logiki biznesowej tylko w didSet/willSet czyni kod nieprzezroczystym
  • Nieprawidłowe zarządzanie efektami ubocznymi przy "pustym" zmianie wartości, gdy nie zmieniła się ona
  • Używanie obserwatorów dla obliczanych właściwości zamiast realizacji behawioru w setterze

Przykład z życia

Negatywny przypadek

Programista zaimplementował w didSet aktualizację interfejsu, ale nie kontrolował zmiany wartości. UI był aktualizowany nawet przy "pustym" przypisaniu, co obniżyło wydajność.

Zalety:

  • Szybka implementacja, mało kodu

Wady:

  • Wzrosła liczba niepotrzebnych operacji, utrudniona debugowanie

Pozytywny przypadek

W didSet sprawdzano równość starej i nowej wartości. Aktualizacja interfejsu następowała tylko wtedy, gdy wartość naprawdę się zmieniła.

Zalety:

  • Minimalizacja efektów ubocznych, wysoka wydajność

Wady:

  • Wymagana dodatkowa kontrola if, trochę więcej kodu