Właściwości static i class to właściwości należące do typu, a nie do instancji. Historycznie pojawiły się, aby rozwiązać problem przechowywania informacji wspólnej dla wszystkich instancji (np. liczników, konfiguracji, fabryk). W Swift static można używać we wszystkich typach (class, struct, enum), a class — tylko w klasach i tylko dla właściwości obliczanych, zapewniając możliwość nadpisania w dziedziczeniu.
Problem: niewłaściwe użycie właściwości statycznych może prowadzić do sytuacji wyścigu i błędów przy dostępie z różnych wątków. Łatwo również pomylić static z class i niewłaściwie wybrać mechanizm do przesłonięcia w dziedziczeniu.
Rozwiązanie:
Przykład kodu:
class Counter { static var count = 0 static let queue = DispatchQueue(label: "counter.queue") static func increment() { queue.sync { count += 1 } } class var typeDescription: String { return "Generic Counter" } } class NamedCounter: Counter { override class var typeDescription: String { return "Named Counter" } }
Kluczowe cechy:
Pytanie 1: Czy można zadeklarować static let property jako właściwość obliczaną (computed)?
Tak, static property może być zarówno przechowywaną, jak i obliczaną. Dla let właściwości to zazwyczaj stała, jednak static var z powodzeniem może być obliczana:
struct Math { static var pi: Double { return 3.1415926 } }
Pytanie 2: Czy static var jest bezpieczne dla wątków domyślnie?
Nie, jeśli static var jest zmieniane z różnych wątków, mogą wystąpić sytuacje wyścigu. operacje read/write muszą być synchronizowane ręcznie.
Pytanie 3: Czy można używać class var dla przechowywanych właściwości?
Nie, class var zawsze musi być właściwością obliczaną (property with get/optional set), właściwości przechowywane są dozwolone tylko dla static.
W aplikacji licznik wejść użytkownika był przechowywany w static var i inkrementowany z różnych wątków bez synchronizacji.
Zalety:
Wady:
Dla globalnego obiektu konfiguracyjnego użyto static let i dostęp do niego był tylko do odczytu lub z wykorzystaniem DispatchQueue do zapisu.
Zalety:
Wady: