Grand Central Dispatch (GCD) pojawił się w iOS i macOS już w 2009 roku jako system niskiego poziomu do organizacji kodu konkurencyjnego, asynchronicznego (wielowątkowość), oparty na kolejkach — DispatchQueue. GCD okazał się znacznie bardziej zwięzły niż ręczne zarządzanie wątkami, zapewniając bezpieczne wykonywanie zadań, synchronizację i wygodne API.
Asynchroniczność i wielowątkowość tradycyjnie są źródłem większości problemów: wyścigi danych, martwe blokady, zawieszanie interfejsu i skomplikowane awarie. Niewłaściwe użycie kolejek lub próby odwołania się do UI z nie-głównego wątku prowadzą do błędów.
Swift pozwala łatwo tworzyć pracę w tle i bezpiecznie wracać na główny wątek w celu aktualizacji interfejsu za pomocą kolejek globalnych i użytkownika. Użyj DispatchQueue do pracy asynchronicznej i DispatchGroup, jeśli musisz poczekać na zakończenie zestawu zadań asynchronicznych.
Przykład kodu:
let backgroundQueue = DispatchQueue(label: "background", qos: .background) backgroundQueue.async { // wykonuje się w tle let image = downloadImage() DispatchQueue.main.async { // bezpieczna aktualizacja UI imageView.image = image } }
Kluczowe cechy:
Co się stanie, jeśli wywołasz sync na głównej kolejce z głównego wątku?
Wystąpi martwa blokada: główny wątek czeka na wykonanie zadania w samym sobie, a aplikacja „zamrozi się”.
DispatchQueue.main.sync { // MARTWA BLOKADA }
Czy DispatchQueue.serial może wykonywać zadania równolegle?
Nie, kolejka szeregowa zawsze wykonuje zadania jedno po drugim, jednak jeśli utworzysz kilka kolejek szeregowych, one będą się wykonywać równolegle między sobą.
Czy dozwolone jest aktualizowanie interfejsu nie z głównego wątku?
Nie, wszelkie manipulacje z UIKit (lub renderingiem SwiftUI) można wykonywać tylko z DispatchQueue.main. Naruszenie tego zasady prowadzi do niestabilnej pracy i awarii.
W tle pobierane są dane, od razu aktualizowany jest UI — aplikacja czasami się zawiesza lub interfejs się zamraża. Dodatkowo, używają wspólnego stanu między wątkami bez synchronizacji.
Zalety:
Wady:
Organizacja wszystkich aktualizacji UI tylko na DispatchQueue.main, dedykowane kolejki do pracy z dużymi danymi, wykorzystanie DispatchGroup do kontroli zakończenia zadań asynchronicznych.
Zalety:
Wady: