- 여러 개의 비동기 작업을 모니터링하여 모든 작업이 완료되면 다음 작업을 수행하도록 하는 행동 즉, 다수의 네트워크 요청을 동시에 보내고, 모든 요청이 완료되면 UI를 업데이트 하거나 다른 작업을 수행하는 등의 상황에서 유용하다. (이미지를 동시에 다 다운받고 확인할 때, 런치스크린과 첫 화면 예시)
- 다수의 큰 작업을 작은 조각으로 분할하여 각각을 병렬로 처리하고, 전체 작업이 완료되었는지를 추적하여 알리는 행동 즉, 대규모 데이터 처리 또는 이미지/동영상 처리 등의 작업
let group = DispatchGroup()
someQueue.async(group: group) { ... }
someQueue.async(group: group) { ... }
someOtherQueue.async(group: group) { ... }
group.notify(queue: DispatchQueue.main) { [weak self] in
self?.textLabel = text = "All jobs have completed"
}
let group = DispatchGroup()
let queue = DispatchQueue.global(qos: .userInitiated)
queue.async(group: group) {
print("Start job 1")
Thread.sleep(until: Date().addingTimeInterval(10))
print("End job 2")
}
queue.async(group: group) {
print("Start job 2")
Thread.sleep(until: Date().addingTimeInterval(2))
print("End job 2")
}
if group.wait(timeout: .now() + 5) == .timedOut {
print("I got tired of waiting")
} else {
print("All the jobs have completed")
}
let group = DispatchGroup()
let queue = DispatchQueue.global(qos: .userInitiated)
queue.async(group: group) {
print("Start job 1")
Thread.sleep(until: Date().addingTimeInterval(10))
print("End job 1")
}
group.wait()
queue.async(group: group) {
print("Start job 2")
Thread.sleep(until: Date().addingTimeInterval(2))
print("End job 2")
}
queue.dispatch(group: group) {
// count is 1
group.enter()
// count is 2
someAsyncMethod {
defer { group.leave() }
// Perfrom your work here.
// count goes back to 1 once complete
}
}
let group = DispatchGroup()
// unsplash.com 무료 이미지 사이트
let base = "https://images.unsplash.com/photo-"
let imageNames = [
"1579962413362-65c6d6ba55de?ixlib=rb-1.2.1&auto=format&fit=crop&w=934&q=80","1580394693981-254c3aeded6a?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=3326&q=80", "1579202673506-ca3ce28943ef?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=934&q=80", "1535745049887-3cd1c8aef237?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=934&q=80", "1568389494699-9076492b22e7?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=937&q=80", "1566624790190-511a09f6ddbd?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=934&q=80"
]
let userQueue = DispatchQueue.global(qos: .userInitiated)
var downloadedImages: [UIImage] = []
// for 문으로 다 도는 시간이 엄청 빠름
// enter로 모든 항목 +되고, URLSession clousre 내부 안에서 활동은 시간이 좀 걸림
// 그 항목들이 하나식 끝날 때마다 group이 마이너스 되다가
// group이 다 끝나면 notify 발동
for name in imageNames {
guard let url = URL(string: "\(base)\(name)") else { continue }
group.enter()
// URL세션 자체가 비동기적 작업의 처리라는 것을 인식할 필요
let task = URLSession.shared.dataTask(with: url) { data, _, error in
// defer로 클로저의 마지막에 사용하도록 등록할 수있음
defer { group.leave() }
if error == nil, let data = data, let image = UIImage(data: data) {
downloadedImages.append(image)
}
}
task.resume()
}
group.notify(queue: userQueue) {
downloadedImages
print("=====모든 다운로드 완료=====")
PlaygroundPage.current.finishExecution()
}
import UIKit
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
//: # 디스패치세마포어(DispatchSemaphore)
//: ### 수기신호: 공유리소스에 접근가능한 작업 수를 제한해야하는 경우
let group = DispatchGroup()
let queue = DispatchQueue.global(qos: .userInteractive)
// unsplash.com 무료 이미지 사이트
let base = "https://images.unsplash.com/photo-"
let imageNames = [
"1579962413362-65c6d6ba55de?ixlib=rb-1.2.1&auto=format&fit=crop&w=934&q=80","1580394693981-254c3aeded6a?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=3326&q=80", "1579202673506-ca3ce28943ef?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=934&q=80", "1535745049887-3cd1c8aef237?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=934&q=80", "1568389494699-9076492b22e7?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=937&q=80", "1566624790190-511a09f6ddbd?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=934&q=80"
]
let userQueue = DispatchQueue.global(qos: .userInitiated)
let downloadSemaphore = DispatchSemaphore(value: 4)
var downloadedImages: [UIImage] = []
for name in imageNames {
guard let url = URL(string: "\(base)\(name)") else { continue }
group.enter()
downloadSemaphore.wait()
let task = URLSession.shared.dataTask(with: url) { data, _, error in
defer {
downloadSemaphore.signal()
group.leave()
}
if error == nil, let data = data, let image = UIImage(data: data) {
downloadedImages.append(image)
}
}
task.resume()
}
group.notify(queue: userQueue) {
print("=====모든 다운로드 완료=====")
downloadedImages
PlaygroundPage.current.finishExecution()
}
제가 학습한 내용을 요약하여 정리한 것입니다. 내용에 오류가 있을 수 있으며, 어떠한 피드백도 감사히 받겠습니다.
감사합니다.