Я пытаюсь использовать gRPC у React Native. Во-первых, мне удалось настроить мой модуль gRPC с помощью Objective-C. Затем я создал собственный модуль для этого модуля 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);
}
Модуль с возвращаемым значением (на самом деле, с обещанием)
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([email protected]);
Ошибка компиляции, но во время запуска приложения XCode возвращает эту ошибку времени выполнения в строке RCT_REMAP_METHOD "com.facebook.React.JavaScript(11): EXC_BAD_ACCESS (код = 1, адрес = 0x88)
Похоже, что с макросом RCT_REMAP_METHOD что-то не так, но не знаю деталей Objective-C и не знаю, как использовать marco.
Если есть кто-то, кто знает, как использовать макрос RCT_REMAP_METHOD для экспорта модуля с параметром и возвращаемым значением или если что-то не так с моим кодом, пожалуйста, дайте мне знать.
Дополнительный поиск Я следовал определению RCT_REMAP_METHOD, и кажется, что использовать RCT_EXPORT_METHOD вместо этого можно, потому что EXPORT переопределяет REMAP, и есть пример Promises с 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.
*
*/
Как я уже упоминал в дополнительной части поиска, мне удалось экспортировать модуль с параметром и возвращаемым значением с помощью 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
- это просто remap
функцию js на встроенную функцию. Это полезно, когда несколько собственных методов одинаковы до первого двоеточия и имеют конфликтующие имена JavaScript.
Как определить RCT_REMAP_METHOD(js_name, method)
, js_name
означает функцию, 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
}
}
}
Убедитесь, что
RCTPromiseResolveBlock
иRCTPromiseRejectBlock
являются последними двумя параметрами.