GCD에는 global queue, main queue 두가지 유형이 있다.
global queue는 main queue를 제외한 여러 큐가 있는것이다. 보통 동시성 작업을 수행하려고 할 때 쓴다. sync, async둘 다 가능함.
근데 main queue는 단 하나의 큐이다. UI작업을 수행할 때 씀! 이건 async밖에 안되는 것으로 알고 있다.
@IBAction func onLoadSync(_ sender: Any) {
let image = loadImage(from: IMAGE_URL)
imageView.image = image
}
@IBAction func onLoadAsync(_ sender: Any) {
// TODO: async
DispatchQueue.global().async{
let image = self.loadImage(from: self.IMAGE_URL)
DispatchQueue.main.async{
self.imageView.image = image
}
}
}
private func loadImage(from imageUrl: String) -> UIImage? {
guard let url = URL(string: imageUrl) else { return nil }
guard let data = try? Data(contentsOf: url) else { return nil }
let image = UIImage(data: data)
return image
}
만약 global queueu를 sync하게 하면 이건 마찬가지로 동기적으로 작업이 된다.
UIImage에다가 image를 그리는 것은 main queue에서 해야하기 때문에 저렇게 코드를 작성해준 것.
PromiseKit이란 것도 있는데, 이것과 다르게 Rx가 뜬 이유는 operator때문.
예시로 뭔가 비동기 작업을 수행하다가 취소를 하고 싶을 때, rx에서는 굉장히 쉽게 할 수 있다.
@IBAction func onLoadImage(_ sender: Any) {
imageView.image = nil
rxswiftLoadImage(from: LARGER_IMAGE_URL)//rxswiftLoadImage는 Observable객체를 반환함. 이 Observable을 관찰할 스케줄러를 지정해줘야하는데, 그게 observeOn임.
.observeOn(MainScheduler.instance)//dispatchqueue의 main thread에서 UI작업을 해 준 것과 같은 역할.
.subscribe({ result in // disposable을 반환함.
switch result {
case let .next(image):
self.imageView.image = image
case let .error(err):
print(err.localizedDescription)
case .completed:
break
}
}).disposed(by: disposeBag)
}
취소 작업을 구현하는 여러가지 방법이 있지만, 여기서는 disposeBag을 보여준다.
저 .disposed(by: disposeBag)이라는 것은 disposeBag에다가 disposable객체를 넣어주는 것이다.
@IBAction func onCancel(_ sender: Any) {
// TODO: cancel image loading
//disposable?.dispose()
disposeBag = DisposeBag() // disposeBag을 새로 할당하면 초기화가 되는식임.
}
disposeBag이라는 것은 안에 비우는 delete나 이런게 없기때문에, 그냥 새로운 가방을 할당하는게 disposable객체를 없애는 방법이다.