新聞中心
有時一個應(yīng)用程序需要訪問平臺 API,React Native 并沒有相應(yīng)的封裝器。也許你想重用現(xiàn)有的一些 Objective——C 或 C++ 代碼,無需在 JavaScript 上重新實(shí)現(xiàn)?;蛘邔懸恍└咝阅埽嗑€程的代碼,如圖像處理、網(wǎng)絡(luò)堆棧,數(shù)據(jù)庫或渲染。

創(chuàng)新互聯(lián)專注為客戶提供全方位的互聯(lián)網(wǎng)綜合服務(wù),包含不限于成都做網(wǎng)站、網(wǎng)站設(shè)計(jì)、遼寧網(wǎng)絡(luò)推廣、小程序開發(fā)、遼寧網(wǎng)絡(luò)營銷、遼寧企業(yè)策劃、遼寧品牌公關(guān)、搜索引擎seo、人物專訪、企業(yè)宣傳片、企業(yè)代運(yùn)營等,從售前售中售后,我們都將竭誠為您服務(wù),您的肯定,是我們最大的嘉獎;創(chuàng)新互聯(lián)為所有大學(xué)生創(chuàng)業(yè)者提供遼寧建站搭建服務(wù),24小時服務(wù)熱線:028-86922220,官方網(wǎng)址:www.cdcxhl.com
我們設(shè)計(jì) React Native,這樣可以為你寫真正的本地代碼,并且能夠訪問整個平臺。這是一個更高級的特性,且我們并不期望它成為通常開發(fā)過程的一部分,但是它的存在是至關(guān)重要的。如果 React Native 不支持你需要的本地特性,那么你應(yīng)該能夠自己構(gòu)建它。
這是一個更高級的指南,展示了如何構(gòu)建一個本地模塊。它假設(shè)讀者知道 Objective-C(Swift 還沒有支持)和核心庫(Foundation,UIKit)。
iOS 日歷模塊的例子
本指南將使用 iOS 日歷 API 的例子。假設(shè)我們希望能夠從 JavaScript 訪問 iOS 日歷。
Native 模塊只是一個 Objectve-C 類,實(shí)現(xiàn)了 RCTBridgeModule 協(xié)議。如果你想知道,RCT 是 ReaCT 的一個簡稱。
// CalendarManager.h #import "RCTBridgeModule.h" #import "RCTLog.h" @interface CalendarManager : NSObject@end
React Native 不會向 JavaScript 公開任何 CalendarManager 方法,除非有明確的要求。幸運(yùn)的是有了 RCT_EXPORT,這會非常簡單:
// CalendarManager.m
@implementation CalendarManager
- (void)addEventWithName:(NSString *)name location:(NSString *)location
{
RCT_EXPORT();
RCTLogInfo(@"Pretending to create an event %@ at %@", name, location);
} @end現(xiàn)在從你的 JavaScript 文件中,你可以像這樣調(diào)用方法:
var CalendarManager = require('NativeModules').CalendarManager;
CalendarManager.addEventWithName('Birthday Party', '4 Privet Drive, Surrey');注意,導(dǎo)出的方法名稱是從 Objective-C 選擇器的第一部分中生成的。有時它會產(chǎn)生一個非慣用的 JavaScript 名稱(就像在我們的例子中的那個)。你可以通過為 RCT_EXPORT 提供一個可選參數(shù)更改名字,如 RCT_EXPORT(addEvent)。
方法返回的類型應(yīng)該是 void。React Native 橋是異步的,所以向 JavaScript 傳遞結(jié)果的唯一方法是使用回調(diào)或 emitting 事件(見下文)。
參數(shù)類型
React Native 支持多種參數(shù)類型,可以從 JavaScript 代碼傳遞到 native 模塊:
字符串型(
NSString)數(shù)字型(
NSInteger,float,double,CGFloat,NSNumber)布爾型(
BOOL,NSNumber)這個列表中任何類型的數(shù)組(
NSArray)這個列表中任何類型的字符串鍵和值的映射(
NSDictionary)函數(shù)(
RCTResponseSenderBlock)
在我們的 CalendarManager 示例中,如果我們想把事件日期傳遞到 native,我們必須將它轉(zhuǎn)換成一個字符串或一個數(shù)字:
- (void)addEventWithName:(NSString *)name location:(NSString *)location date:(NSInteger)secondsSinceUnixEpoch
{
RCT_EXPORT(addEvent); NSDate *date = [NSDate dateWithTimeIntervalSince1970:secondsSinceUnixEpoch];
}隨著 CalendarManager.addEvent 方法變得越來越復(fù)雜,參數(shù)的數(shù)量將會增加。其中一些可能是可選的。在這種情況下對改變 API 一點(diǎn)來接受事件屬性的字典是值得考慮的,如:
#import "RCTConvert.h"
- (void)addEventWithName:(NSString *)name details:(NSDictionary *)details
{
RCT_EXPORT(addEvent); NSString *location = [RCTConvert NSString:details[@"location"]]; // ensure location is a string
...
}并且從 JavaScript 調(diào)用它:
CalendarManager.addEvent('Birthday Party', {
location: '4 Privet Drive, Surrey', time: date.toTime(),
description: '...'
})注意:關(guān)于數(shù)組和映射
React Ntive 沒有為這些結(jié)構(gòu)中值的類型提供任何擔(dān)保。你的 native 模塊可能期望一個字符串?dāng)?shù)組,但如果 JavaScript 調(diào)用你的包含數(shù)字和字符串?dāng)?shù)組的方法,你會得到帶有
NSNumber和NSString的NSArray。檢查數(shù)組/映射值類型是開發(fā)人員的責(zé)任 (助手方法見RCTConvert)。
回調(diào)
警告
本節(jié)比其他更具有實(shí)驗(yàn)性,圍繞回調(diào)我們沒有得到一組最佳實(shí)踐。
Native 模塊還支持一種特殊的參數(shù)——回調(diào)。在大多數(shù)情況下它是用來向 JavaScript 提供函數(shù)調(diào)用結(jié)果的。
- (void)findEvents:(RCTResponseSenderBlock)callback
{
RCT_EXPORT(); NSArray *events = ...
callback(@[[NSNull null], events]);
}RCTResponseSenderBlock 只接受一個參數(shù)——參數(shù)的數(shù)組傳遞給 JavaScript 的回調(diào)。在本例中,我們使用節(jié)點(diǎn)的慣例來為 error 和其他的——函數(shù)的結(jié)果設(shè)置第一個參數(shù)。
CalendarManager.findEvents((error, events) => { if (error) { console.error(error);
} else { this.setState({events: events});
}
})Native 模塊應(yīng)該只調(diào)用它的回調(diào)一次。然而,它可以將回調(diào)作為 ivar 存儲并稍后調(diào)用回調(diào)。這種模式通常用于包裝需要委托的 iOS 的 APIs。請看 RCTAlertManager。
如果你想向 JavaScript 傳遞 error ——如對象,使用 RCTUtils.h 的 RCTMakeError。
實(shí)現(xiàn) native 模塊
Native 模塊應(yīng)該沒有任何關(guān)于什么線程正在被調(diào)用的假設(shè)。React Native 在一個單獨(dú)的串行 GCD 隊(duì)列中調(diào)用 native 模塊方法,但這是一個實(shí)現(xiàn)細(xì)節(jié),可能會改變。如果 native 模塊需要調(diào)用 main-thread-only iOS API,它應(yīng)該在主隊(duì)列安排操作:
- (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 模塊不應(yīng)該阻塞。使用 dispatch_async 在后臺隊(duì)列中安排耗費(fèi)大的工作是一個好主意。
導(dǎo)出常量
Native 模塊可以在運(yùn)行時向 JavaScript 導(dǎo)出立即可用的常量。導(dǎo)出一些初始數(shù)據(jù)是有用的,否則這些初始數(shù)據(jù)需要往返的橋梁。
- (NSDictionary *)constantsToExport
{ return @{ @"firstDayOfTheWeek": @"Monday" };
}JavaScript 能夠立即使用這些值:
console.log(CalendarManager.firstDayOfTheWeek);
注意,只有在初始化時常量才能被導(dǎo)出,所以如果你在運(yùn)行時改變了 constantsToExport 的值,它不會影響 JavaScript 環(huán)境。
發(fā)送事件到 JavaScript
Native 模塊可以在不被直接調(diào)用的情況下向 JavaScript 發(fā)送事件信號。最簡單的方法是使用 eventDispatcher:
#import "RCTBridge.h"
#import "RCTEventDispatcher.h"
@implementation CalendarManager
@synthesize bridge = _bridge;
- (void)calendarEventReminderReceived:(NSNotification *)notification
{ NSString *eventName = notification.userInfo[@"name"];
[self.bridge.eventDispatcher sendAppEventWithName:@"EventReminder"
body:@{@"name": eventName}];
} @endJavaScript 代碼可以訂閱這些事件:
var subscription = DeviceEventEmitter.addListener( 'EventReminder', (reminder) => console.log(reminder.name) ); ...// Don't forget to unsubscribe subscription.remove();
更多的向 JavaScript 發(fā)送事件的例子,請看 RCTLocationObserver。
當(dāng)前題目:創(chuàng)新互聯(lián)React教程:Native 模塊(iOS)
轉(zhuǎn)載注明:http://m.fisionsoft.com.cn/article/cdiohds.html


咨詢
建站咨詢
