디스패치큐(GCD) 사용시 주의해야할 사항

junseole·2021년 11월 3일
post-thumbnail

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 메서드 주의사항 ( 절대 해서는 안되는 코드 2가지)

  1. 메인큐에서 다른 큐로 보낼때 sync메서드를 사용하면 안된다.

    메인큐에서는 항상 비동기적으로 보내야한다.

    UI와 관련되지 않은 오래걸리는 작업들은 다른 쓰레드에서 일을 할 수 있도록 비동기적으로 실행해야 하며, 동기적으로 시키면 UI가 버벅이는 현상 발생

  2. 현재의 큐에서 현재의 큐로 "동기적으로" 보내서는 안된다.

    현재의 큐를 블락하는 동시에 다시 현재의 큐에 접근하기 때문에 교착상황(DeadLock)이 발생

    DispatchQueue.global().async{
      DispatchQueue.global().sync{
        
      }
    }

    다른 쓰레드로 보내지면 교착상태는 발생하지 않지만 같은 쓰레드에 보내진다면 교착상태가 발생한다. 이러한 가능성때문에 저런식의 코드를 쓰면 안된다.

weak, strong 캡처 주의

작업을 보내는일은 클로저를 보내는것이다.

객체에 대한 캡처 현상이 발생한다.

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?) -> ()){
  //코드
}

캡처리스트 [weak self]에 대한 이해

DispatchQueue.global().async{ [weak self] in
       DispatchQueue.main.async{
         
       }}
// 내부 클로저에는 weak self 선언 불필요 

ARC

Heap 메모리 할당되는 메모리 관리를 위해 ARC 방법으로 메모리 관리

강한 참조 사이클이 일어나면 메모리 누수가 발생한다.

클래스 인스턴스

변수를 weak, unowned 로 인스턴스를 참조하되 RC가 올라가지 않아 강한 참조 사이클 일어나지 않음

클로저

클로저의 캡처리스트 내에서 weak, unowned로 선언하여 인스턴스를 참조하되 RC가 올라가지 않게 하므로 강한 참조 사이클 일어나지 않음

profile
Swift와 함께 여행중입니다.

0개의 댓글