본문 바로가기

개발/Swift

[Swift] Multithreading

반응형

iOS API 의 Multithreading 예시를 살펴보자.

let session = URLSession(configuration: .default)

if let url = URL(string: "http://djgmd1021...") {
    let task = session.dataTask(with: url) { (data: Data?, response, error) in
    
    }
    task.resume()
}

URLSession은 네트워크를 통해 URL에서 정보를 가져올 때 사용한다.
URL로 session에 dataTask 함수를 호출하면 dataTask를 생성하는데, 이것은 데이터를 가져오는 일을 한다.
그 후 실행이 일시 중지되는데 바로 다음 라인에 대부분 실행을 재개하라는 명령(resume)을 하고 동작은 다시 시작되게 된다.

 

let session = URLSession(configuration: .default)

if let url = URL(string: "http://djgmd1021...") {
    let task = session.dataTask(with: url) { (data: Data?, response, error) in
        DispatchQueue.main.async {
            // UI 작업
        }
    }
    task.resume()
}

task 는 클러저를 사용하고 있는데 이 클로저는 매인 큐의 밖에서 실행되고 있다.
만약 여기서 UI와 관련된 작업을 하고 싶다면 여기서 메인 큐로 작업을 보내야 한다.

 

if let url = imageURL {
    DispatchQueue.global(qos: .userInitiated).async {
        let urlContents = try? Data(contentsOf: url)
        if let imageData = urlContents {
            self.image = UIImage(data: imageData)
        }
    }
}

실행 작업이 오래걸리는 것은 global queue로 옮겨준다.
멀티스레딩에서 .self를 사용할 때 다른 것도 생각해봐야한다.

이 self를 포함한 코드의 바로 전 과정이 실행하는데, 
해당 뷰 컨트롤러가 더 이상 있지 않을 때까지 
오래 걸리면 어떻게 할까?
이 클로저의 self에 의해 힙에 붙잡혀 있다면 어떻게 될까?
이런 경우에는 weak self를 사용하는게 좋다.

if let url = imageURL {
    DispatchQueue.global(qos: .userInitiated).async { [weak self] in
        let urlContents = try? Data(contentsOf: url)
        if let imageData = urlContents {
            self?.image = UIImage(data: imageData)
        }
    }
}

메모리 사이클과는 관련이 없지만, 클로저에 의해 self가 힙에 붙잡혀 있는 것을 막기 위해서이다.
만약 이 클로저가 실행되는데 너무 오래 걸려서 사용자가 취소했을 때
weak self가 self를 더 신경쓰지 않게 해준다.

 

if let url = imageURL {
    DispatchQueue.global(qos: .userInitiated).async { [weak self] in
        let urlContents = try? Data(contentsOf: url)
        DispatchQueue.main.async {
          if let imageData = urlContents {
              self?.image = UIImage(data: imageData)
          }
        }
    }
}

위와 같이 들어간 코드는 메인큐가 한가할 때 메인큐에서 실행될 것이다.

 

if let url = imageURL {
    DispatchQueue.global(qos: .userInitiated).async { [weak self] in
        let urlContents = try? Data(contentsOf: url)
        DispatchQueue.main.async {
          if let imageData = urlContents, url == self?.imageURL {
              self?.image = UIImage(data: imageData)
          }
        }
    }
}

여러 번을 요청을 눌렀을 때 요청한 것이 맞는지 한 번 더 확인하자.

반응형

'개발 > Swift' 카테고리의 다른 글

[Swift] 객체 저장 - Archiving  (0) 2021.02.28
[Swift] 객체 저장 - UserDefaults  (0) 2021.02.28
[Swift] DispatchQueue 종류  (0) 2021.02.26
[Swift] ViewController LifeCycle  (0) 2021.02.26
[Swift] Interface  (0) 2021.02.26