if let url = URL(string: urlString) {
if let data = try? Data(contentsOf: url) {
parse(json: data)
return
}
}
1, 2의 이유로 위 코드가 잘못되었다는 것을 알 수 있다. 모든 UI코드는 메인스레드에서 실행되어야하고 Data contentof로 메인스레드를 막게 되므로 전체 프로그램이 정지되고 사용자는 화면에서 아무것도 할 수 없게된다.
데이터가 다운로드되면 프로그램 정지가 해제되지만 이것은 끔찍한 경험이다..
일반적으로 원격 리소스에 접근하는 경우 백그라운드 스레드에서 수행해야한다.
GCD는 멀티스레딩으로 알려진 여러 스레드를 만들고 작업하는 번거로움을 줄여준다.
스레드 생성, 소멸이나 현재 장치에 대해 최적의 스레드 수를 생성했는지 확인할 필요가 없다.
GCD는 자동으로 스레드를 생성하고 가장 효율적인 방법으로 스레드에서 코드를 실행한다.
: 가장 중요한 GCD함수로 "다음 코드를 비동기식으로 실행" 을 의미한다.
일부 코드를 백그라운드 스레드로 푸시하거나, 메인 스레드로 푸시하여 메인스레드에서 안전하게 ui를 업데이트할 수 있다.
async()를 호출하는 방법은 코드를 실행할 위치를 시스템에 알리는 것이다.
GCD는 queue와 매우 유사하게 작동한다.
GCD 호출은 실행할 스레드를 생성하는 것이 아니라 기존의 스레드 중 하나에 할당되는 것이다.
GCD는 여러 queue를 생성하고 중요도에 따라 작업을 배치한다.
모두 FIFO이기 때문에 코드 블록은 삽입된 순서대로 queue에서 제거되지만 둘 이상의 코드 블럭이 동시에 실행될 수 있기 때문에 완료 순서는 보장되지 않는다.
일부 코드의 중요도는 QoS(quality of service)에 따라 달라진다.
QoS위에는 메인스레드에서 실행되는 main queue가 있고 그 뒤에 사용할 네 개의 background queue가 있으며 각각은 QoS 레벨이 설정되어있다.
DispatchQueue.global().async{
async()를 사용하여 모든 로딩 코드가 백그라운드 큐에서 실행되도록 함
DispatchQueue.global(qos: .userInitiated).async() {
default대신 적절한 qos를 지정하고 싶다면 다음과 같이 작성한다.
async() 메서드는 하나의 매개변수를 가지는데 비동기적으로 실행되는 클로져이다. 후행 클로져 구문을 사용한다. 강한 참조 주기가 없도록 하기 위해서 [weak self]로 시작한다고 생각할 수 있지만 GCD는 코드를 한 번 실행한 다음 버리기 때문에 그렇지 않다.
DispatchQueue.global(qos: .userInitiated).async() {
if let url = URL(string: urlString) {
if let data = try? Data(contentsOf: url) {
parse(json: data)
return
}
}
}
사용자 인터페이스 작업을 백그라운드 스레드에서 수행하는것은 절대 좋지 않다.
만약 지금 백그라운드 스레드에 있고 메인스레드에서 코드를 실행하고 싶다면 async()를 다시 호출하면된다.
Dispatch.main.async() {
self.tableView.reloadData()
}
: GCD를 사용하는 또다른 방법으로 performSelector(inBackground:)와 performSelector(onMainThread:)가 있다.
둘 다 같은 방식으로 작동된다. inBackground는 백그라운드 스레드에서 실행하고 onMainThread는 메인 스레드에서 실행한다.
tableView.performSelector(onMainThread: #selector(UITableView.reloadData), with: nil, waitUntilDone: false)