React Native(RCT_REMAP_METHOD):如何导出带有参数和 return 值的方法?

React Native(RCT_REMAP_METHOD) : How to export a method with a parameter and return value?

我正在尝试在 React Native 中使用 gRPC。 首先,我能够使用 Objective-C 设置我的 gRPC 模块。 接下来,我为那个 gRPC 模块制作了一个原生模块。

gRPC 模块非常简单。

rpc CheckEmail(EmailCheckRequest) returns (EmailCheckResponse) {}

message EmailCheckRequest {
    string email = 1;
}

message EmailCheckResponse {
    common.RetCode ret = 1; 
}

如您所见,有一个输入参数(电子邮件地址)和 return 一个 "Return Code"。

我在 https://facebook.github.io/react-native/docs/native-modules-ios.html 检查了如何制作本机模块,它显示了如何制作带有参数的模块或带有 return 值的模块,但它没有解释如何制作两者兼而有之。

示例如下。

带参数的模块

RCT_EXPORT_METHOD(addEvent:(NSString *)name)
{
  RCTLogInfo(@"Pretending to create an event %@", name);
}

具有 return 值的模块(实际上,有 Promise)

RCT_REMAP_METHOD(findEvents,
                 findEventsWithResolver:(RCTPromiseResolveBlock)resolve
                 rejecter:(RCTPromiseRejectBlock)reject)
{
  NSArray *events = ...
  if (events) {
    resolve(events);
 } else {
    NSError *error = ...
    reject(@"no_events", @"There were no events", error);
  }
}

反正我是基于这个,自己写的代码是这样的

RCT_REMAP_METHOD(checkEmail: (NSString *)email, resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
{
    /* ... */
}

而react-native端javascript代码是这样的。 var 网络服务 = NativeModules.NetworkService; var ret = NetworkService.checkEmail('spike@merong.com');

没有编译错误,但是 运行 应用程序 XCode return 在 RCT_REMAP_METHOD 行出现此运行时错误 "com.facebook.React.JavaScript (11):EXC_BAD_ACCESS(代码=1, 地址=0x88)

看来RCT_REMAP_METHOD宏有问题,但不知道Objective-C细节,也不知道如何使用宏。

如果有人知道如何使用 RCT_REMAP_METHOD 宏来导出带有参数和 return 值的模块,或者如果我的代码有问题,请告诉我。

其他发现 我按照RCT_REMAP_METHOD的定义,好像用RCT_EXPORT_METHOD代替也可以,因为EXPORT是REMAP的重新定义,有一个Promises with EXPORT的例子,但不确定是否正确这样做的方法。

* ## Promises
 *
 * Bridge modules can also define methods that are exported to JavaScript as
 * methods that return a Promise, and are compatible with JS async functions.
 *
 * Declare the last two parameters of your native method to be a resolver block
 * and a rejecter block. The resolver block must precede the rejecter block.
 *
 * For example:
 *
 * RCT_EXPORT_METHOD(doSomethingAsync:(NSString *)aString
 *                           resolver:(RCTPromiseResolveBlock)resolve
 *                           rejecter:(RCTPromiseRejectBlock)reject
 * { ... }
 *
 * Calling `NativeModules.ModuleName.doSomethingAsync(aString)` from
 * JavaScript will return a promise that is resolved or rejected when your
 * native method implementation calls the respective block.
 *
 */

正如我在附加发现部分提到的,我能够导出一个带有参数和 return 值的模块 RCT_EXPORT_METHOD。

RCT_EXPORT_METHOD(checkEmail: (NSString *)email 
    resolver:(RCTPromiseResolveBlock)resolve 
    rejecter:(RCTPromiseRejectBlock)reject)
{
    /* ... */
}

通过这种方式,我能够导出 "checkEmail"。

Javascript : NativeModules.ModuleName.checkEmail(电子邮件);

我没有Objective-C背景知识,所以即使这样工作,如果我的代码有问题,请告诉我。 =)

RCT_EXPORT_METHOD只是把js函数remap转为native函数。当多个本机方法在第一个冒号之前相同并且具有冲突的 JavaScript 名称时,这很有用。

作为定义RCT_REMAP_METHOD(js_name, method)js_name表示从js代码调用的函数,method表示原生函数名。

所以如果你想导出一个带有参数(或更多)的方法,你可以这样做:

// Bridge.m

RCT_EXPORT_MODULE(Bridge)

RCT_REMAP_METHOD(findEvents,
                 type:(NSString *)type
                 params:(NSDictionary *)params
                 findEventsWithResolver:(RCTPromiseResolveBlock)resolve
                 rejecter:(RCTPromiseRejectBlock)reject)
{ ... }

然后从js代码中调用函数如下:

const Bridge = NativeModules.Bridge;

class App extends Component {
  asnyc _buttonPress() {
    try {
      let result = await Bridge.findEvents("type", {"key": "value"});
      // handle the result
    } catch(e) {
      // handle the error
    }
  }
}

Make sure the RCTPromiseResolveBlock and RCTPromiseRejectBlock are the last two parameters.