Search code examples
swiftreact-nativepromisereact-native-iosbridge

How to bridge a Swift Promise to React Native


I'm integrating an iOS native SDK into React-Native. There's a function called SDK.getCardData which I want to use from RN. My first attempt was to call resolve and reject inside the closure:

import Foundation
import SDK

@objc(SwiftComponentManager)
class SwiftComponentManager: NSObject {
  
  @objc
  func getCardData(_ resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void {
    let cardId: String = "test"
    let secret: String = "test"

    SDK.getCardData(cardId, secret: secret) { (cardData, error) in
      if (error != nil) {
        reject(String(format: "Card data request failed: %@", error!.localizedDescription))
      } else {
        let pan = cardData!.pan
        let cvv = cardData!.cvv

        resolve(String(format: "Card data fetched successfully, pan: %@, cvv: %@", pan, cvv))
      }
    }
  }

  @objc func testMethod() -> Void {
    print("This Does appear")
  }
}

Unfortunately this throws the following error: escaping closure captures non-escaping parameter 'resolve'.

Second attempt:

import Foundation
import SDK
import Promises

@objc(SwiftComponentManager)
class SwiftComponentManager: NSObject {
  
  @objc
  func getCardData(_ resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Promise<CardData?> {
    let cardId: String = "test"
    let secret: String = "test"
    let promise = Promise<CardData?>()

    SDK.getCardData(cardId, secret: secret) { (cardData, error) in
      if (error != nil) {
        promise.reject(error)
      } else {
        let pan = cardData!.pan
        let cvv = cardData!.cvv

        promise.resolve(cardData)
      }
    }
    
    return promise
  }

  @objc func testMethod() -> Void {
    print("This Does appear")
  }
}

How to call the resolve & reject properly? It is important for the function to return Void, more here.


Solution

  • Found the answer, Just had to add @escaping to the arguments:

    @objc func fling(_ options: NSDictionary, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) -> Void {
    ...