
iOS Concurrency(동시성) 프로그래밍, 동기 비동기 처리 그리고 GCD/Operation - 디스패치큐와 오퍼레이션큐의 이해를 보고 정리한 글입니다.
UI관련일들은 "메인큐"에서 처리해야 한다.
DispatchQueue.global().async{
//코드 1
//코드 2
DispatchQueue.main.async{
//다운로드 한 이미지 표시 코드
self.imageView.image = image // UI 관련 작업들은 메인큐에서 진행
}
}
//URLSession은 내부적으로 비동기 처리가 되어있음
URLSession.shared.dataTask(with: url){
//코드 1
//코드 2
DispatchQueue.main.async{
//다운로드 한 이미지 표시 코드
self.imageView.image = image // UI 관련 작업들은 메인큐에서 진행
}
}
메인큐에서 다른 큐로 보낼때 sync메서드를 사용하면 안된다.
메인큐에서는 항상 비동기적으로 보내야한다.
UI와 관련되지 않은 오래걸리는 작업들은 다른 쓰레드에서 일을 할 수 있도록 비동기적으로 실행해야 하며, 동기적으로 시키면 UI가 버벅이는 현상 발생
현재의 큐에서 현재의 큐로 "동기적으로" 보내서는 안된다.
현재의 큐를 블락하는 동시에 다시 현재의 큐에 접근하기 때문에 교착상황(DeadLock)이 발생
DispatchQueue.global().async{
DispatchQueue.global().sync{
}
}
다른 쓰레드로 보내지면 교착상태는 발생하지 않지만 같은 쓰레드에 보내진다면 교착상태가 발생한다. 이러한 가능성때문에 저런식의 코드를 쓰면 안된다.
작업을 보내는일은 클로저를 보내는것이다.
객체에 대한 캡처 현상이 발생한다.
DispatchQueue.global(qos:.utility).async{[weak self] in
guard let self = self else { return }
DispatchQueue.main.async{
self.textLabel.text = "New posts updated!"
}
}

작업이 아직 종료하지 않았는데, 해당 값에 접근하면, 잘못된 값을 사용할 확률이 높다.
해당 비동기 작업이 끝났다는 것을 정확히 알려주는 시점이 컴플리션핸들러(completionHandler)이다.
비동기 함수와 관련된 작업들은 모두 컴플리션핸들러를 가지고 있다
//예 @escaping 클로저가 종료되고 호출 (비동기 클로저에 필수적으로 있어야한다)
func tiltShift(_ inputImage: UIImage?, runQueue: DispatchQueue, completionQueue: DispatchQueue, completion: @escaping (UIImage?, Error?) -> ()){
//코드
}
DispatchQueue.global().async{ [weak self] in
DispatchQueue.main.async{
}}
// 내부 클로저에는 weak self 선언 불필요
Heap 메모리 할당되는 메모리 관리를 위해 ARC 방법으로 메모리 관리
강한 참조 사이클이 일어나면 메모리 누수가 발생한다.
변수를 weak, unowned 로 인스턴스를 참조하되 RC가 올라가지 않아 강한 참조 사이클 일어나지 않음
클로저의 캡처리스트 내에서 weak, unowned로 선언하여 인스턴스를 참조하되 RC가 올라가지 않게 하므로 강한 참조 사이클 일어나지 않음