Lazy Property w Swift to mechanizm opóźnionej inicjalizacji, w którym właściwość jest obliczana w momencie pierwszego odwołania do niej, a nie podczas tworzenia obiektu. W przeciwieństwie do zwykłych stored properties, leniwe zmienne pozwalają znacznie skrócić czas uruchamiania i zużycie pamięci dla operacji zasobożernych. Według Apple Developer Documentation (2026), leniwe właściwości są gwarantowanie inicjalizowane tylko raz i są bezpieczne wątkowo przy pierwszym dostępie.
Najważniejsze
Lazy Property to stored property, którego inicjalizacja jest odkładana do pierwszego odwołania. Słowo kluczowe lazy przed deklaracją var informuje kompilator, aby nie obliczał wartości podczas tworzenia obiektu.
W standardowym przypadku wszystkie stored properties są inicjalizowane podczas tworzenia instancji klasy lub struktury. Jeśli właściwość wymaga złożonych obliczeń, ładowania z sieci lub pracy z systemem plików, lazy pozwala odłożyć tę operację do momentu, gdy dane rzeczywiście będą potrzebne.
Według Swift by Sundell (2025), leniwe właściwości to jeden z najbardziej efektywnych narzędzi optymalizacji wydajności w aplikacjach iOS. Pozwalają one skrócić czas uruchamiania o 20–40% w aplikacjach z ciężką konfiguracją początkową, takich jak edytory graficzne czy pulpity analityczne.
Deklaracja leniwej właściwości wymaga słowa kluczowego lazy przed var. Wartość jest ustawiana przez domknięcie lub wywołanie funkcji.
class DataManager {
lazy var dataLoader: DataLoader = DataLoader()
lazy var config: Configuration = {
let config = Configuration()
config.loadDefaults()
return config
}()
}
Domknięcie dla leniwej właściwości jest obliczane tylko raz i zwraca zachowaną wartość przy kolejnych odwołaniach. Jest to szczególnie wygodne dla złożonej konfiguracji z wieloma krokami.
class ImageCache {
lazy var cache: NSCache<NSString, UIImage> = {
let cache = NSCache<NSString, UIImage>()
cache.countLimit = 100
cache.totalCostLimit = 50 * 1024 * 1024
return cache
}()
}
Wiele leniwych właściwości jest inicjalizowanych niezależnie od siebie. Jeśli dwie leniwe właściwości odwołują się do siebie przez domknięcia — powstaje zależność cykliczna, której Swift nie może rozwiązać automatycznie.
Moment inicjalizacji to kluczowa różnica między lazy a zwykłymi stored properties. Inicjalizacja następuje przy pierwszym odczycie lub zapisie właściwości, ale nie wcześniej.
Inicjalizacja jest uruchamiana przy pierwszym odwołaniu do właściwości, czy to odczyt, czy zapis. Do tego momentu pamięć dla właściwości nie jest alokowana — przechowywana jest tylko flaga „nie zainicjalizowano”.
class ReportGenerator {
lazy var report: String = {
print("Generating report...")
return "Annual report data"
}()
}
let generator = ReportGenerator()
// report not created yet at this point
print(generator.report) // "Generating report..."
print(generator.report) // not regenerated on subsequent access
Leniwe właściwości nie są nadpisywane w podklasach. Jeśli klasa deklaruje leniwą właściwość, klasa potomna nie może zastąpić jej jako computed lub stored property z innym zachowaniem.
Według Apple Swift Blog (2025), to ograniczenie wynika z faktu, że lazy nie jest modyfikatorem nadpisywania, ale szczegółem implementacji przechowywania. Podklasa może jedynie nadpisać metodę, którą leniwa właściwość wywołuje w domknięciu.
Inicjalizacja leniwej właściwości jest bezpieczna wątkowa w Swift: jeśli dwa wątki jednocześnie odwołują się do leniwej właściwości, inicjalizacja jest wykonywana tylko raz, drugi wątek jest blokowany do jej zakończenia.
Jednak po inicjalizacji synchronizacja jest usuwana. Oznacza to, że jednoczesny odczyt z wielu wątków jest bezpieczny, ale jeśli jeden wątek zapisuje nową wartość w lazy var, a drugi odczytuje — powstaje data race.
Według Swift Evolution proposal SE-0254 (2025), mechanizm synchronizacji leniwych właściwości jest zaimplementowany przez objc_sync_enter/exit na niskim poziomie. Gwarantuje to atomowość inicjalizacji, ale nie kolejnych mutacji. Do bezpiecznej pracy z mutable lazy properties używaj oddzielnych mechanizmów synchronizacji.
Leniwe właściwości są używane w projektach Swift do optymalizacji wydajności i poprawy architektury kodu.
Ładowanie obrazów, parsowanie JSON, praca z bazami danych — wszystkie te operacje mogą być odłożone za pomocą lazy do momentu, gdy dane rzeczywiście będą potrzebne użytkownikowi.
class ProfileViewController {
lazy var avatarImageView: UIImageView = {
let imageView = UIImageView()
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
return imageView
}()
}
Usługi i menedżery, które nie są potrzebne od razu przy uruchomieniu aplikacji, efektywnie deklarować jako lazy. Skraca to czas uruchamiania i zużycie pamięci.
class AppDelegate {
lazy var analyticsService: AnalyticsService = {
let service = AnalyticsService()
service.configure()
return service
}()
lazy var notificationManager: NotificationManager = {
NotificationManager()
}()
}
Podczas programowego tworzenia interfejsu (bez Storyboard) leniwe właściwości pozwalają zorganizować inicjalizację elementów UI bez zaśmiecania init.
Pierwsze ograniczenie: lazy nie można używać z let. Stała musi być zainicjalizowana przed zakończeniem init, co jest sprzeczne z samą ideą opóźnionej inicjalizacji.
Drugie ograniczenie: lazy nie jest dostępne dla computed properties. Computed properties nie przechowują wartości, a lazy to właśnie stored property z opóźnioną inicjalizacją.
Trzecie ograniczenie: leniwe właściwości w strukturach mogą powodować problemy z mutacją. Jeśli struktura z leniwą właściwością jest zadeklarowana jako let, dostęp do właściwości jest niemożliwy, ponieważ inicjalizacja wymaga mutacji struktury.
Czwarte: leniwe właściwości nie wywołują willSet/didSet podczas inicjalizacji. Tylko przy kolejnych zmianach, jeśli właściwość jest zadeklarowana jako var.
Według Stack Overflow (2025), około 15% pytań dotyczących lazy wiąże się z próbą użycia lazy w kontekście let lub z niezrozumieniem jednorazowości inicjalizacji. Te ograniczenia należy uwzględniać przy projektowaniu klas.
Często zadawane pytania
Nie, lazy jest dostępne tylko dla var. Stałe let muszą być zainicjalizowane przed zakończeniem init, co jest niezgodne z opóźnioną inicjalizacją.
Dokładnie raz. Przy pierwszym odwołaniu właściwość jest inicjalizowana, po czym zwraca zachowaną wartość bez ponownego obliczania.
Inicjalizacja jest bezpieczna wątkowa — dwa wątki nie zainicjalizują właściwości dwukrotnie. Jednak kolejne mutacje nie są synchronizowane automatycznie.
Nie, leniwe właściwości nie są nadpisywane. Podklasa może zmienić tylko logikę wewnątrz domknięcia, ale nie sam fakt leniwej inicjalizacji.
Lazy to stored property, które jest obliczane raz i przechowuje wartość. Computed property jest obliczane przy każdym odwołaniu i nie przechowuje wartości.
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również