Swift

Swift - 비동기 처리 (Completion Handler)

iosos 2023. 7. 15. 16:28

Completion Handler

- 비동기 작업이 완료되었을 때 실행되는 코드 블록 (callback)

- 주로 비동기 작업의 결과나 상태를 전달하고 처리하는 용도로 사용 

- 비동기 작업이 완료되면 그 결과를 즉시 처리 

 

- 일반적으로 함수의 매개변수로 전달되며, 작업이 완료된 후에 호출

- 이때 작업의 성공 여부나 결과 등을 전달 가능

- 일반적으로 'Result' 타입이나 옵셔널, 매개변수 목록을 이용하여 결과 전달 

 

 

 

 

 

비동기적으로 데이터를 가져오는 함수 예시

func fetchData(completion: @escaping (Result<Data, Error>) -> Void) {
    let url = URL(string: "https://example.com/data")!
    URLSession.shared.dataTask(with: url) { (data, response, error) in
        if let error = error {
            completion(.failure(error))
        } else if let data = data {
            completion(.success(data))
        } else {
            // 데이터가 없는 경우에 대한 처리
        }
    }.resume()
}

- 'fetchData(completion:)' 함수 : 비동기적으로 데이터 가져오고 작업이 완료되면 Completion Handler를 호출하여 결과 전달

- Completion Hander는 'Result<Data, Error>' 타입을 받음

- 작업의 성공시 'Result.success(data)' 전달

- 작업 실패시 'Result.failure(data)' 전달 

- 작업이 완료되면 Result<Data, Error> 타입의 결과와 성공 여부 전달 

 

- @escaping : 클로저가 함수의 범위를 벗어나서 실행될 수 있음을 알림. 작업이 완료 후 completion Handler가 호출될 때 클로저가 함수 외부에서 실행되기 때문에 @escaping 키워드 사용 

- 외부에서 실행되는 클로저는 아래 ViewDidLoad()에서 실행 중인 'fetchData { result in ...}' 부분을 뜻함

 

- '(Result<Data, Error>) -> Void' : 클로저 타입

- Result<Data, Error> 타입으로 입력을 받고 반환 값이 없는 Void 형태를 가지는 함수. 성공 또는 실패의 결과를 나타내는 열거형 

 

 

 

fetchData(completion:) 함수 호출

    override func viewDidLoad() {
        super.viewDidLoad()
        
        fetchData { result in
            switch result {
            case .success(let data):
                // 데이터를 가져오는 작업이 성공한 경우
                self.handleSuccess(data: data)
            case .failure(let error):
                // 데이터를 가져오는 작업이 실패한 경우
                self.handleError(error: error)
            }
        }
    }

- fetchData를 실행하고 비동기 작업이 완료되면 { result in ... } 클로저를 실행하는 구문 

 

- fetchData(completion:) 함수를 호출하면 비동기 작업이 시작

- 작업이 완료되면 completion handler 호출 

- completion handler의 매개변수 'result' 는 Result<Data, Error> 타입으로 작업의 성공 여부와 결과 전달 

- 비동기 작업의 결과에 따라 result를 분기하여 처리 

- 성공하면 handleSuccess() 메서드를 호출하여 data를 처리, 실패하면 handleError() 메서드 호출하여 에러 처리

 

 

 

 


전체 코드

import UIKit

class CompletionViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        fetchData { result in
            switch result {
            case .success(let data):
                // 데이터를 가져오는 작업이 성공한 경우
                self.handleSuccess(data: data)
            case .failure(let error):
                // 데이터를 가져오는 작업이 실패한 경우
                self.handleError(error: error)
            }
        }
    }
    
    
    
    func fetchData(completion: @escaping (Result<Data, Error>) -> Void) {
        let url = URL(string: "https://example.com/data")!
        URLSession.shared.dataTask(with: url) { (data, response, error) in
            if let error = error {
                completion(.failure(error))
            } else if let data = data {
                completion(.success(data))
            } else {
                // 데이터가 없는 경우에 대한 처리
            }
        }.resume()
    }
    
    
    
    func handleSuccess(data: Data) {
        // 데이터를 성공적으로 처리하는 로직
    }
    
    func handleError(error: Error) {
        // 에러를 처리하는 로직
    }
}

 

 

 

참고)

https://lxxyeon.tistory.com/202 

 

[iOS] CompletionHandler 다루기

UIKit, 네트워크 통신같은 비동기 처리가 필요할 때 꼭 알아야 하는 CompletionHandler 다루기! 사전에 closure에 대한 이해가 필요 [Swift] 클로져(Closure) 기본 클로저(Closure) 란? - 클로저(Closure)란 코드에서

lxxyeon.tistory.com

 

'Swift' 카테고리의 다른 글

Swift - UIKit, SnapKit 비교  (0) 2023.07.23
Swift - PickerView  (0) 2023.07.19
Swift - 비동기처리(async / await)  (0) 2023.07.14
Swift - sort, sorted 함수 비교  (0) 2023.07.13
Swift - 고차함수 (compactMap, flatMap)  (0) 2023.07.12