DispatchQueue
작업항목의 실행을 관리하는 클래스
Queue에 추가된 작업항목은 시스템이 관리하는 스레드 풀에서 처리하고, 작업을 완료하면 스레드를 알아서 제거
일반 스레드 코드보다 쉽고, 효율적으로 코드를 작성할 수 있음
서버에서 데이터를 내려받을 때, 이미지나 동영상 등의 멀티미디어 처리와 같이 CPU 사용량이 많은 처리를 별도의 스레드에서 처리
➡️ 메인 스레드로 결과를 전달해 화면에 표시
DispatchQueue 생성시 Serial이 기본, attribute를 따로 주면 Concurrent 유형으로 바꿀 수 있음
+
OperationQueue: Operation을 OperationQueue에 제출하면 Concurrent operation 객체를 만들어 줌
DispatchQueue로 비동기 프로그래밍
guard let url: URL = URL(string: " ~~ url ~~ ") else { return }
let session: URLSession = URLSession(configuration: .default)
let dataTask: URLSessionDataTask = session.dataTask(with: url) { (data: Data?, response: URLResponse?, error: Error?) in
if let error = error {
print(error.localizedDescription)
return
}
guard let data = data else { return }
do {
let apiResponse: APIResponse = try
JSONDecoder().decode(APIResponse.self, from: data)
self.friends = apiResponse.results
// UI 관련 작업은 메인 스레드에서 !
DispatchQueue.main.async {
self.tableView.reloadData()
}
} catch(let arr) {
print(err.localizedDescription)
}
}
dataTask.resume()
// 이를 호출해주면 이 때 dataTask를 실행하고 서버에 요청
URLRequest의 경우 값을 가져온 뒤 자동으로 메인 스레드로 돌아오지 않기 때문에
DispatchQueue.main.async 코드에 넣어서 메인 스레드에서 작업하도록 해 주어야 함
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
...
cell.imageView?.image = nil
// 셀이 재사용되기 전에 셀의 이미지뷰의 이미지를 없애줘야 함
// 이미지를 가져오기 전에 다른 셀의 이미지가 표현되지 않도록
// placeholder 이미지를 넣어주면 좋음
// global : 백그라운드에서 동작하는 큐
DispatchQueue.global().async {
guard let imageURL: URL = URL(string: friends.picture.thumbnail) else { return }
guard let imageData: Data = try? Data(contentsOf: imageURL) else { return }
// UI 관련 작업은 메인에서
DispatcheQueue.main.async {
// 이미지를 다운받는 동안 화면을 움직여 셀의 Index가 바뀌면?
// 셀이 데이터를 setting 해주고 있는 현재의 index와, 이미지 다운이 끝났을 때의 index가 달라질 수 있음
// -> 이를 구분해주고 서로 일치하는 상황에서만 이미지를 setting
if let index: IndexPath = tableView.indexPath(for: cell) {
if index.row == indexPath.row {
cell.imageView?.image = UIImage(data: imageData)
}
}
}
}
return cell
}
DispatchQueue.main.asyncAfter : 코드를 일정 시간 뒤에 실행하고자 할 때 사용
DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
print("print")
}
'iOS' 카테고리의 다른 글
[iOS] Photos - 날짜 순으로 에셋 가져오기 (0) | 2020.06.08 |
---|---|
[iOS] Photos Framework (0) | 2020.06.08 |
[iOS] 서버에 데이터 요청하기 : URLSessionDataTask (0) | 2020.06.08 |
[iOS] URLSession과 URLSessionDataTask (0) | 2020.06.08 |
[iOS] Grand Central Dispatch (GCD) (0) | 2020.06.08 |