React Native教程 中文版<四> Native模块交互
Native 模块(iOS)有时一个应用程序需要访问平台 API,React Native 并没有相应的封装器。也许你想重用现有的一些 Objective——C 或 C++ 代码,无需在 JavaScript 上重新实现。或者写一些高性能,多线程的代码,如图像处理、网络堆栈,数据库或渲染。 我们设计 React Native,这样可以为你写真正的本地代码,并且能够访问整个平台。这是一个更高级的特性,且我们并不期望它成为通常开发过程的一部分,但是它的存在是至关重要的。如果 React Native 不支持你需要的本地特性,那么你应该能够自己构建它。 这是一个更高级的指南,展示了如何构建一个本地模块。它假设读者知道 Objective-C(Swift 还没有支持)和核心库(Foundation,UIKit)。 iOS 日历模块的例子本指南将使用iOS 日历 API 的例子。假设我们希望能够从 JavaScript 访问 iOS 日历。 Native 模块只是一个 Objectve-C 类,实现了 // CalendarManager.h
#import "RCTBridgeModule.h"
"RCTLog.h"
@interface CalendarManager : NSObject <RCTBridgeModule>
@end
React Native 不会向 JavaScript 公开任何 // CalendarManager.m
@implementation CalendarManager
- (void)addEventWithName:(NSString *)name location:(NSString *)location
{
RCT_EXPORT();
RCTLogInfo(@"Pretending to create an event %@ at %@",name,location);
}
现在从你的 JavaScript 文件中,你可以像这样调用方法:
并且从 JavaScript 调用它: CalendarManager.addEvent(time: date.toTime(),description: '...'
})
回调警告 Native 模块还支持一种特殊的参数——回调。在大多数情况下它是用来向 JavaScript 提供函数调用结果的。 void)findEvents:(RCTResponseSenderBlock)callback
{
RCT_EXPORT();
NSArray *events = ...
callback(@[[NSNull null],events]);
}
CalendarManager.findEvents((error,events) => {
if (error) {
console.error(error);
} else {
this.setState({events: events});
}
})
Native 模块应该只调用它的回调一次。然而,它可以将回调作为 ivar 存储并稍后调用回调。这种模式通常用于包装需要委托的 iOS 的 APIs。请看 如果你想向 JavaScript 传递 error ——如对象,使用 实现 native 模块Native 模块应该没有任何关于什么线程正在被调用的假设。React Native 在一个单独的串行 GCD 队列中调用 native 模块方法,但这是一个实现细节,可能会改变。如果 native 模块需要调用 main-thread-only iOS API,它应该在主队列安排操作: - (void)addEventWithName:(NSString *)name callback:(RCTResponseSenderBlock)callback
{
RCT_EXPORT(addEvent);
dispatch_async(dispatch_get_main_queue(),^{
// Call iOS API on main thread ... // You can invoke callback from any thread/queue callback(@[...]);
});
}
同样的方法,如果操作要很长时间才能完成,native 模块不应该阻塞。使用 导出常量Native 模块可以在运行时向 JavaScript 导出立即可用的常量。导出一些初始数据是有用的,否则这些初始数据需要往返的桥梁。 - (NSDictionary *)constantsToExport
{
return @{ @"firstDayOfTheWeek": @"Monday" };
}
JavaScript 能够立即使用这些值: console.log(CalendarManager.firstDayOfTheWeek);
注意,只有在初始化时常量才能被导出,所以如果你在运行时改变了 发送事件到JavaScript Native 模块可以在不被直接调用的情况下向 JavaScript 发送事件信号。最简单的方法是使用 "RCTBridge.h"
"RCTEventDispatcher.h"
CalendarManager
@synthesize bridge = _bridge;
- (void)calendarEventReminderReceived:(NSNotification *)notification
{
NSString *eventName = notification.userInfo[@"name"];
[self.bridge.eventDispatcher sendAppEventWithName:@"EventReminder"
body:@{@"name": eventName}];
}
JavaScript 代码可以订阅这些事件:
|