iOS 개발 기록

[Swift] CompletionHandler 본문

iOS/비동기처리

[Swift] CompletionHandler

택꽁이 2023. 2. 6. 13:23
728x90

CompletionHandler

📄 목차

completionHandler

func login(loginData: Login, completionHandler: @escaping () -> Void) {
    guard let webview = self.webview else { return }
    webview.evalFlexFunc("login", sendData: loginData) { data in
      log.debug(" PMS LOGIN! ")
      completionHandler()         // ❗️실수하기 쉬운 포인트
    }
}

// 사용 
login(loginData: signInInfo) { 
    print("로그인 성공")
}
  • @escaping 을 통해 콜백 기반 comopletionHandler를 실행.
  • 단점 :
  1. 깜빡하고 completionHandler를 실행하지 않을 경우 컴파일러가 에러를 안뱉음.
  2. completionHandler를 많이 오출해야 하는 경우 무수한 콜백 지옥
  3. self를 사용할 경우 강한 참조 사이클에 주의해야 한다.
  4. 코드가 안예쁘대.

Combine

func login(loginData: Login) -> AnyPublisher <Void, Never> {
    return Future() { promise in
      guard let webview = self.webview else { return }
      webview.evalFlexFunc("login", sendData: loginData) { data in
        log.debug(" PMS LOGIN! ")
      }
      promise(.success(()))
    }.eraseToAnyPublisher()
  }
}

// 사용 
login(loginData: signInInfo)
    .sink(receiveValue: { _ in
      print("로그인 완료")
    })
    .store(in: &cancellable)
  • completionHandler는 combine의 Future를 통해 대체 가능.
  • Future를 통해 발행된 데이터는 sink와 같은 subscriber를 통해 전달 받을 수 있다.
  • Future : 로직을 수행한 후 비동기로 성공과 실패를 전달하는 publisher.
    성공할 경우 promise를 통해 element를 전달한다.
  • 단점 : 아래는 단점이라기보단 개인적인 느낌
  1. Combine를 import 해야함.
  2. 위와 같이 다른 작업 없이 완료한 내용만 알리는 거라면 굳이 combine을 사용해야하나?

SwiftConcurrency

func login(loginData: Login) async {
    guard let webview = self.webview else { return }
    await webview.evalFlexFunc("login", sendData: loginData) { data in
      log.debug(" PMS LOGIN! ")
    }
  }

// 사용
Task{
  await self.bridgeAction?.login(loginData: signInInfo)
}
  • 참고

Apple Developer Documentation

Combine v.s. Async/Await

'iOS > 비동기처리' 카테고리의 다른 글

[Concurrency] AsyncStream  (0) 2023.04.07
[Concurrency]Continuation  (0) 2023.04.04
[Concurrency] async / await  (0) 2023.02.06