[iOS][SeSAC] DispatchGroup

·2024년 1월 31일

global qos(quality of service)

업무의 우선순위에 따라 작업 순서를 조절할 수 있다

DispatchQueue.global(qos: .background).async {
    for i in 201...300 {
        print(i, terminator: " ")
    }
}
        
DispatchQueue.global(qos: .userInitiated).async {
    for i in 301...400 {
        print(i, terminator: " ")
   }
}
  • background
    가장 우선순위가 낮음

  • userInitiated
    사용자의 제스처가 들어가는 부분, 애니메이션에 사용



DispatchGroup

작업 중인 여러 메모리를 한 묶음으로 표현하고 마지막 실행 완료를 알려준다. 작업은 메모리들이 나눠서 받되, 각각의 메모리에서 실행 완료 후 group에 알려주고 group은 모든 메모리들이 작업 완료되면 notify한다

let group = DispatchGroup()
        
DispatchQueue.global().async(group: group) {
    for i in 1...100 {
        print(i, terminator: " ")
    }
}
        
DispatchQueue.global().async(group: group) {
    for i in 101...200 {
        print(i, terminator: " ")
    }
}
        
DispatchQueue.global().async(group: group) {
    for i in 201...300 {
        print(i, terminator: " ")
    }
}
        
DispatchQueue.global().async(group: group) {
    for i in 301...400 {
         print(i, terminator: " ")
    }
}
        
// 작업 끝나면 알려줄 수 있는데 작업 중인 메모리에게 작업 끝난 거 알려줄까?
group.notify(queue: .main) {
     print("finished")
}

그런데, 위 예제는 맡은 일이 동기적이므로(print만 하니까)
비동기 작업 안에 비동기 작업이 들어가 있는 경우는 다르게 처리해야 한다.
왜냐하면, notify는 동기 함수에서만 유효하고 네트워크 통신과 같은 비동기 함수가 group에 묶이게 되면, 비동기 함수는 또 다른 메모리가 담당하게 되기 때문에, 다른 메모리의 일을 기다리지 않고 notify를 바로 띄우게 되기 때문

그렇다면 비동기 작업 안에 비동기 작업이 들어가 있는 경우는 어떻게 해결할까?
-> enter / leave

let id = [616037, 672, 246655, 634649]
        
let group = DispatchGroup()
        
// 나 작업 들어갈게
group.enter() // DispatchGroup은 +1 값을 가지게 된다.(reference count)
DispatchQueue.global().async(group: group) {
    TMDBAPIManager.shared.fetchTrendingMovie { movie in
        self.list = movie
        // 나 할 일 완료 했어
        group.leave()   // -1
    }
}
    
group.enter()
DispatchQueue.global().async(group: group) {
    TMDBAPIManager.shared.fetchMovieImages(id: 112538) { poster in
        self.imageList[0] = poster
        group.leave()
    }
}
        
group.enter()
DispatchQueue.global().async(group: group) {
    TMDBAPIManager.shared.fetchMovieImages(id: 112545) { poster in
        self.imageList[1] = poster
        group.leave()
    }
}
        
group.enter()
DispatchQueue.global().async(group: group) {
    TMDBAPIManager.shared.fetchMovieImages(id: 235289) { poster in
        self.imageList[2] = poster
        group.leave()
    }
}
        
group.enter()
DispatchQueue.global().async(group: group) {
    TMDBAPIManager.shared.fetchMovieImages(id: 212471) { poster in
        self.imageList[3] = poster
        group.leave()
    }
}
        
group.notify(queue: .main) {
    self.tableView.reloadData()
    self.collectionView.reloadData()
}

0개의 댓글