본문 바로가기
UIKit/기본

컴플리션 핸들러 - 비동기 처리 (함수가 끝난 후 결과 알려줄 때)

by 밤새는탐험가 2024. 3. 19.

컴플리션 핸들러 (Completion Handler) 이란?

어떠한 작업이 완료된 이후에 진행되는 작업을 담당한다. 

 

▶️ 작업이 끝나면 "return" 키워드를 통해 전달하는 게 아니라 클로저로 전달해야 한다.

(return: 비동기 작업을 기다리지 않고, 바로 반환하기 때문에 "nil" 이 나온다.)◀️

 

▶️ 클로저는 주로 비동기 작업에 많이 사용된다.

그래서 비동기적인 어떠한 태스크가 끝나고 나서 수행해야 할 블록을 

클로저로 작성하면 편리하다. ◀️

 

 

컴플리션 핸들러는 어떻게 사용하나?

 

doSomething 메서드 내부에 DispatchQueue를 통해 print() 메서드 동작에 딜레이를 적용했다.

(딜레이를 적용하여 비동기 상황을 재연함)

 

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        print("ViewController - viewDidLoad() 호출")
        doSomething()
        
    }
    
    private func doSomething() {
        print("ViewController - doSomething() 호출")
        
        DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
            print("DispatchQueue.main.asynceAfter() 호출")
        }
    }
}

 

 

 

 

doSomething() 메서드를 커스텀 컴플리션 블록 구문으로 만들면?

즉 비동기 처리를 하기 위한 구문을 만든다고 보면 된다. 

 

doSomething() 메서드 내부에 2초가 지난 후에 completion("호출 완료") 라는 결과를

(doSomething() 메서드가 끝난다는 것을)

ViewDidLoad() 메서드 내부에서 호출한 doSomething() 메서드로 알려준다. 

 

▶️ 보통은 함수가 끝난 것을 알 수가 없는데, 컴플리션 블럭을 통해 알 수 있다. ◀️

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        print("ViewController - viewDidLoad() 호출")
        doSomething { result in
            print("completion block으로 호출: \(result)")
        }
        
    }
    
    private func doSomething(completion: @escaping(String) -> ()) {
        print("ViewController - doSomething() 호출")
        
        DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
            // print("DispatchQueue.main.asynceAfter() 호출")
            completion("호출 완료")
        }
    }
}

 

 

 

실제로는 어떻게 사용하나?

KRProgressHUD 라는 오픈소스를 사용했다.

 

doSomething() 메서드는 컴플리션 블럭을 통해 2초가 지난 후에 

"호출 완료" 라는 값을 알려준다.

 

ViewDidLoad() 메서드 내부에서 doSomething() 메서드를 호출하면

정해진 시간이 지난 후에  KRProgressHUD.showSuccess() 표시되고

mainTitle에 "호출 완료" 라는 값을 할당한다.

 

import UIKit
import KRProgressHUD

class ViewController: UIViewController {
    
    @IBOutlet weak var mainTitle: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        print("ViewController - viewDidLoad() 호출")
        
        KRProgressHUD.show()
        doSomething { result in
            print("completion block으로 호출: \(result)")
            KRProgressHUD.showSuccess()
            
            self.mainTitle.text = result
        }
        
    }
    
    private func doSomething(completion: @escaping(String) -> ()) {
        print("ViewController - doSomething() 호출")
        
        DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
            // print("DispatchQueue.main.asynceAfter() 호출")
            completion("호출 완료")
        }
    }
}

 

 

'UIKit > 기본' 카테고리의 다른 글

네비게이션 바 + 탭 바 적용  (0) 2024.03.29
Drawing Cycle (+ Layout Cycle)  (0) 2024.03.28
앱의 생명주기 (App Life Cycle)  (0) 2024.03.27
ViewController의 life cycle  (1) 2024.03.27
Delegate Pattern (델리게이트 패턴)  (1) 2024.03.18