I am currently implementing a third party SDK that uses the delegate pattern to fire callbacks when async functions are completed. This SDK is used to unlock bluetooth doors. Here is a high level view of how the code behaves. The library is for a vendor so I'm just renaming the method but this is exactly how it is written.
RNMYModuleBridge.m
//rndemo RNMyModule.m#import <React/RCTBridgeModule.h>@interface RCT_EXTERN_MODULE(RNMyModule, NSObject)RCT_EXTERN_METHOD(initializeBLESDK: resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject )RCT_EXTERN_METHOD(fetchMobileKeys: resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject )- (dispatch_queue_t)methodQueue{ return dispatch_get_main_queue();}+ (BOOL)requiresMainQueueSetup{ return YES;}@end// end of file
RNMyModule.swift
import BLESDKimport CoreBluetooth@objc(RNMyModule)class RNMyModule: NSObject, BLEManagerDelegate { // Promise resolvers for JS var _resolve: RCTPromiseResolveBlock? var _reject: RCTPromiseRejectBlock? // EXPOSED REACT NATIVE FUNCTIONS @objc func initializeBLESDK(_ UUID: String, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) -> Void { self._resolve = resolve; self._reject = reject; BLEManager.shared().initializeBLESDK(UUID, withDelegate: self); } @objc func fetchMobileKeys(_ Empty: String, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) -> Void { self._resolve = resolve; self._reject = reject; BLEManager.shared().fetchMobileKeys(self) } // DELEGATE CALLBACKS // this method is called after `BLEManager.shared().initializeBLESDK` completes // and it works just fine in my App.js file func initializeBLESDKResponse(_ response: String!, status endpointStatus: Bool) { if (endpointStatus) { self._resolve?(response) return } self._reject?(false) } // this method is called after `BLEManager.shared().fetchMobileKeys(self)` completes // HOWEVER: Because fetchMobileKeys scans for devices, this function gets called more than // once by the delegate, each time it completes a scan. The second time this function is // called, my react native applications throws the error: // Illegal callback invocation from native module. This callback type only permits a single // invocation from native code. func fetchMobileKeysResponse(_ response: String!, status keysStatus: Bool) { if (!keysStatus) { return } self.resolve?(reponse); }}
I can't edit the vendor framework as I just get it as a compiled module with a header file to expose the methods that I am using in the above code.
Is there a way to intercept the delegate callback so that I can use the RCTEventEmitter as discussed in this post here: https://medium.com/nycdev/calling-a-callback-multiple-times-in-a-react-native-module-5c3c61f2fca4