В настоящее время я внедряю сторонний SDK, который использует шаблон делегата для запуска обратных вызовов при завершении асинхронных функций c. Этот SDK используется для разблокировки дверей Bluetooth. Вот высокоуровневое представление о поведении кода. Библиотека предназначена для поставщика, поэтому я просто переименовываю метод, но именно так он и написан.
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 BLESDK
import 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);
}
}
Я не могу редактировать структуру вендора, так как я просто получаю ее в виде скомпилированного модуля с файлом заголовка, чтобы показать методы, которые я использую в приведенном выше коде.
Есть ли способ перехватить обратный вызов делегата, чтобы я мог использовать RCTEventEmitter, как описано в этом посте здесь: https://medium.com/nycdev/calling-a-callback-multiple-times-in-a-react-native-module-5c3c61f2fca4