React Native(RCT_REMAP_METHOD):如何使用参数导出方法并返回值?

时间:2017-07-14 09:17:07

标签: javascript ios objective-c react-native grpc

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

gRPC模块非常简单。

rpc CheckEmail(EmailCheckRequest) returns (EmailCheckResponse) {}

message EmailCheckRequest {
    string email = 1;
}

message EmailCheckResponse {
    common.RetCode ret = 1; 
}

如您所见,有一个输入参数(电子邮件地址)并返回"返回代码"。

我检查了如何在https://facebook.github.io/react-native/docs/native-modules-ios.html创建一个本机模块,它显示了如何使用参数或带有返回值的模块创建模块,但它没有解释如何使用两者创建一个模块。

以下是示例。

带参数的模块

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

带有返回值的模块(实际上,带有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)
{
    /* ... */
}

反应本机端javascript代码是这样的。     var NetworkService = NativeModules.NetworkService;     var ret = NetworkService.checkEmail(' spike@merong.com');

没有编译错误,但在运行应用程序时,XCode在RCT_REMAP_METHOD行返回此运行时错误 " com.facebook.React.JavaScript(11):EXC_BAD_ACCESS(code = 1,address = 0x88)

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

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

其他搜索结果 我遵循RCT_REMAP_METHOD的定义,似乎可以使用RCT_EXPORT_METHOD,因为EXPORT是重新定义REMAP,并且有一个带EXPORT的Promises示例,但不确定它是否是正确的方法。

* ## 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.
 *
 */

2 个答案:

答案 0 :(得分:6)

RCT_EXPORT_METHOD只是remap js函数到本机函数。当多个本机方法在第一个冒号之前相同并且具有冲突的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
    }
  }
}
  

确保RCTPromiseResolveBlockRCTPromiseRejectBlock是最后两个参数。

答案 1 :(得分:2)

正如我在其他发现部分所提到的,我能够使用RCT_EXPORT_METHOD导出带参数和返回值的模块。

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

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

Javascript:NativeModules.ModuleName.checkEmail(email);

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