DispatchQueue är en grundläggande kö i Grand Central Dispatch (GCD) ramverket för hantering av asynkrona uppgifter i iOS och macOS. Enligt Apple Developer Documentation, 2026 abstraherar DispatchQueue trådhanteringen från utvecklaren via serial och concurrent-köer. GCD distribuerar automatiskt uppgifter över systemets trådpool, vilket eliminerar manuell skapande och förstöring av trådar.
Huvudpunkter
DispatchQueue är ett objekt i Grand Central Dispatch (GCD) ramverket som hanterar körning av uppgifter i system- eller anpassade trådköer. Grand Central Dispatch är ett lågnivåbibliotek från Apple, tillgängligt sedan iOS 4 och macOS 10.6, som helt abstraherar trådhanteringen från utvecklaren. GCD använder operativsystemets trådpool och skalar automatiskt antalet trådar under enhetens belastning.
Utvecklaren behöver inte manuellt skapa och förstöra trådar — GCD tar över denna uppgift och tillhandahåller ett enkelt API via DispatchQueue. En uppgift i form av en closure skickas till kön via metoderna sync eller async. I det första fallet blockeras den anropande tråden tills uppgiften är slutförd, i det andra fortsätter den omedelbart med körningen.
Enligt Apple (2026) använder GCD systemets trådpool som anpassar sig till antalet kärnor och processorns aktuella belastning. En concurrent-kö skapar inte en ny tråd för varje uppgift — GCD återanvänder trådar från poolen, vilket minimerar overheaden för att skapa trådar.
Grand Central Dispatch består av tre nyckelkomponenter: kön (DispatchQueue), gruppen (DispatchGroup) och semaforen (DispatchSemaphore). Kön är huvudelementet som tar emot uppgifter i form av kodblock. DispatchGroup synkroniserar körningen av flera uppgifter, och DispatchSemaphore begränsar åtkomsten till en delad resurs till ett specifikt antal trådar.
Varje GCD-kö är kopplad till en specifik QoS (Quality of Service)-klass som informerar systemet om uppgiftens betydelse. Systemet använder QoS för att fördela processortid mellan köer, och prioriterar mer kritiska uppgifter — till exempel UI-uppdateringar eller bearbetning av användarberöringar.
Serial-kö utför uppgifter strikt sekventiellt, en efter en. Om tre uppgifter placeras i en serial-kö börjar den andra först efter att den första är helt slutförd. Serial-köer används för att synkronisera åtkomst till delade resurser — till exempel en array som ändras från flera delar av koden.
Concurrent-kö kör flera uppgifter samtidigt och fördelar dem mellan tillgängliga trådar från systempoolen. Uppgifter i en concurrent-kö startar i ankomstordning (FIFO) men slutförs i godtycklig ordning om deras körningstid skiljer sig. Concurrent-kö garanterar inte ordningen för slutförande — bara startordningen.
| Parameter | Serial-kö | Concurrent-kö |
|---|---|---|
| Körningsordning | Strikt sekventiell | Parallell |
| Antal trådar | En | Flera från GCD-poolen |
| Användning | Skydd av delade resurser | Oberoende beräkningar |
| Main queue | Ja (huvudtråden) | Nej |
| Deadlock-risk | Hög vid sync på samma kö | Låg |
Serial-kö är idealisk för uppgifter som ändrar delat tillstånd — skrivning till fil, uppdatering av datamodell eller arbete med Core Data. Användning av serial-kö garanterar att två koddelar inte ändrar samma data samtidigt, vilket eliminerar tävlingsförhållanden utan ytterligare låsningar.
Concurrent-kö passar för uppgifter som inte är beroende av varandra: laddning av flera bilder, parallella nätverksförfrågningar eller batchbearbetning av data. GCD bestämmer automatiskt hur många uppgifter som ska köras samtidigt, baserat på antalet processorkärnor och den aktuella systembelastningen.
QoS (Quality of Service) — en GCD-mekanism som informerar operativsystemet om uppgiftens betydelse och brådska. Systemet använder QoS för trådschemaläggning: uppgifter med högre QoS får mer processortid och startas tidigare. QoS-värdet skickas när en kö skapas eller en specifik uppgift skickas.
I GCD finns fem QoS-klasser tillgängliga. .userInteractive — högsta prioritet för UI-relaterade uppgifter. .userInitiated — för uppgifter som initieras av användaren. .utility — för bakgrundsuppgifter med förloppsindikator. .background — för uppgifter som inte är synliga för användaren. .default — mellannivå mellan userInitiated och utility, används som standard.
Enligt Apple (2026) är felaktigt QoS-val en av de vanligaste orsakerna till prestandaproblem. Att köra en bakgrundsnedladdning med QoS .userInteractive tar resurser från UI:t, vilket orsakar mikro-fördröjningar i animationer. Det rekommenderas att välja den lägsta QoS som fortfarande ger en acceptabel körningstid.
Vid laddning av en bild för omedelbar visning, använd .userInitiated — användaren förväntar sig ett resultat. För förladdning av nästa skärm räcker .utility. Bakgrundssynkronisering med servern utförs med .background, vilket minimerar påverkan på aktiva uppgifter.
DispatchGroup gör det möjligt att följa slutförandet av en grupp uppgifter. När alla uppgifter i gruppen är slutförda anropar GCD notify-hanteraren på den angivna kön. Detta är särskilt användbart vid laddning av flera oberoende resurser — profildata, vänlista och inställningar — när gränssnittet måste uppdateras först efter att all data har mottagits.
DispatchGroup stöder det synkrona anropet wait() som blockerar den aktuella tråden tills alla uppgifter är slutförda. Detta är praktiskt när koden inte kan fortsätta utan gruppens resultat. Den asynkrona varianten — notify() — anropar closuren på den angivna kön efter att alla uppgifter är slutförda, utan att blockera den anropande tråden.
DispatchSemaphore kontrollerar åtkomsten till en resurs och begränsar antalet samtidiga åtkomster. En semafor med startvärde 3 tillåter körning av högst tre parallella uppgifter. Vid anrop av wait() minskas räknaren, vid signal() ökas den. Om räknaren är noll blockeras tråden tills resursen frigörs.
Låt oss titta på tre praktiska exempel på användning av DispatchQueue i Swift. Det första visar ett grundläggande async-anrop med återgång till huvudtråden, det andra — synkronisering via en serial-kö, det tredje — DispatchGroup för parallella förfrågningar.
DispatchQueue.main är serial-kön för huvudtråden, avsedd enbart för UI-operationer. Använd den alltid för att uppdatera gränssnittet efter slutfört bakgrundsarbete.
let queue = DispatchQueue.global(qos: .userInitiated)
queue.async {
let data = self.fetchData()
DispatchQueue.main.async {
self.updateUI(with: data)
}
}
Att skapa en egen serial-kö med en unik identifierare synkroniserar åtkomsten till en föränderlig array. Alla läs- och skrivoperationer går genom en kö, vilket eliminerar tävlingsförhållanden.
let serialQueue = DispatchQueue(label: "com.app.items")
var items: [Int] = []
serialQueue.async {
items.append(1)
}
serialQueue.async {
let last = items.last
DispatchQueue.main.async {
print("Last item: \(last)")
}
}
DispatchGroup gör det möjligt att köra flera uppgifter på en concurrent-kö och få ett meddelande när alla är klara. Detta är användbart vid laddning av data för profilsidan.
let group = DispatchGroup()
let worker = DispatchQueue.global()
worker.async(group: group) { self.loadProfile() }
worker.async(group: group) { self.loadFriends() }
worker.async(group: group) { self.loadSettings() }
group.notify(queue: DispatchQueue.main) {
self.showCompleteUI()
}
Deadlock vid sync-anrop på en serial-kö — det vanligaste misstaget. Om en uppgift på en serial-kö anropar queue.sync på samma kö blockeras tråden permanent. Kön väntar på att den aktuella uppgiften ska slutföras och uppgiften väntar på att sync-anropet ska slutföras — en klassisk ömsesidig blockering.
Alla operationer med UIKit måste utföras på huvudtråden. Xcode upptäcker dessa fel i Debug-läge via Main Thread Checker. I Release-bygge leder de till oförutsägbart beteende: animationer startar inte, UI uppdateras inte, krascher är möjliga.
Att skapa hundratals anpassade köer istället för globala köer är ett antimönster. Varje kö förbrukar systemresurser. För de flesta uppgifter räcker globala concurrent-köer med olika QoS och en eller två serial-köer för synkronisering av delad data.
Vid körning av resursintensiva cykliska uppgifter på en bakgrundskö utan autoreleasepool växer minnet till slutet av hela loopen. ARC frigör objekt endast när autorelease poolen lämnas. Omge loop-iterationer med autoreleasepool { } för tidig minnesfrigöring.
Vanliga frågor
OperationQueue är byggd ovanpå GCD men erbjuder ett API på högre nivå med operationella beroenden, KVO och stöd för avbrytning. DispatchQueue är en lågnivåkö för enkla async-uppgifter utan beroendehantering.
GCD stöder inte stopp av en pågående uppgift. Metoden suspend() pausar endast nya uppgifter, den aktuella körs till slutet. För avbrytning krävs manuell kontroll av en flagga inuti uppgiftskoden.
För den huvudsakliga förfrågan med omedelbar visning av resultatet — .userInitiated. För förladdning av data — .utility. För bakgrundssynkronisering — .background.
GCD fastställer inte antalet trådar. Trådpoolen skalas dynamiskt under belastning, med hänsyn till processorkärnor, aktuell belastning och QoS för varje uppgift. Maximalt antal begränsas av systemet.
UIKit är inte trådsäkert — alla dess klasser måste anropas endast från huvudtråden. Överträdelse orsakar oförutsägbart beteende, missade uppdateringar och krascher i produktion.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också