在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ HTML/ Native 模塊(iOS)
JavaScript 環(huán)境
計(jì)時(shí)器
Native 模塊(iOS)
入門
在設(shè)備上運(yùn)行
ProgressBarAndroid
iOS 應(yīng)用程序狀態(tài)
網(wǎng)絡(luò)
ToolbarAndroid
測(cè)試
輔助功能
網(wǎng)絡(luò)信息
DrawerLayoutAndroid
樣式表
手勢(shì)應(yīng)答系統(tǒng)
與現(xiàn)有的應(yīng)用程序集成
樣式
教程
不透明觸摸
調(diào)試 React Native 應(yīng)用
iOS 活動(dòng)指示器
導(dǎo)航器
無(wú)反饋觸摸
動(dòng)畫布局
Web 視圖
鏈接庫(kù)
像素比率
React Native 官網(wǎng)首頁(yè)介紹
iOS 導(dǎo)航器
交互管理器
全景響應(yīng)器
SwitchAndroid
TabBarIOS.Item
相機(jī)滾動(dòng)
ToastAndroid
iOS 震動(dòng)
BackAndroid
文本輸入
iOS 選擇器
應(yīng)用程序注冊(cè)表
iOS 開(kāi)關(guān)
滾動(dòng)視圖
iOS 日期選擇器
iOS 警告
iOS 鏈接
視圖
圖片
列表視圖
異步存儲(chǔ)
Native UI 組件(Android)
iOS 滑塊
Map 視圖
高亮觸摸
iOS 推送通知
文本
定位
iOS 狀態(tài)欄
Native UI 組件(iOS)
在設(shè)備上運(yùn)行(Android)
Native 模塊(Android)
Flexbox
已知 Issues
iOS 選項(xiàng)卡
安裝 Android 運(yùn)行環(huán)境

Native 模塊(iOS)

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

我們?cè)O(shè)計(jì) React Native,這樣可以為你寫真正的本地代碼,并且能夠訪問(wèn)整個(gè)平臺(tái)。這是一個(gè)更高級(jí)的特性,且我們并不期望它成為通常開(kāi)發(fā)過(guò)程的一部分,但是它的存在是至關(guān)重要的。如果 React Native 不支持你需要的本地特性,那么你應(yīng)該能夠自己構(gòu)建它。

這是一個(gè)更高級(jí)的指南,展示了如何構(gòu)建一個(gè)本地模塊。它假設(shè)讀者知道 Objective-C(Swift 還沒(méi)有支持)和核心庫(kù)(Foundation,UIKit)。

iOS 日歷模塊的例子

本指南將使用 iOS 日歷 API 的例子。假設(shè)我們希望能夠從 JavaScript 訪問(wèn) iOS 日歷。

Native 模塊只是一個(gè) Objectve-C 類,實(shí)現(xiàn)了 RCTBridgeModule 協(xié)議。如果你想知道,RCT 是 ReaCT 的一個(gè)簡(jiǎn)稱。

    // CalendarManager.h
    #import "RCTBridgeModule.h"
    #import "RCTLog.h"
    @interface CalendarManager : NSObject <RCTBridgeModule>
    @end

React Native 不會(huì)向 JavaScript 公開(kāi)任何 CalendarManager 方法,除非有明確的要求。幸運(yùn)的是有了 RCT_EXPORT,這會(huì)非常簡(jiǎn)單:

    // 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 選擇器的第一部分中生成的。有時(shí)它會(huì)產(chǎn)生一個(gè)非慣用的 JavaScript 名稱(就像在我們的例子中的那個(gè))。你可以通過(guò)為 RCT_EXPORT 提供一個(gè)可選參數(shù)更改名字,如 RCT_EXPORT(addEvent)。

方法返回的類型應(yīng)該是 void。React Native 橋是異步的,所以向 JavaScript 傳遞結(jié)果的唯一方法是使用回調(diào)或 emitting 事件(見(jiàn)下文)。

參數(shù)類型

React Native 支持多種參數(shù)類型,可以從 JavaScript 代碼傳遞到 native 模塊:

  • 字符串型(NSString)
  • 數(shù)字型(NSInteger,float,double ,CGFloat,NSNumber)
  • 布爾型(BOOL,NSNumber)
  • 這個(gè)列表中任何類型的數(shù)組(NSArray)
  • 這個(gè)列表中任何類型的字符串鍵和值的映射(NSDictionary)
  • 函數(shù)(RCTResponseSenderBlock)

在我們的 CalendarManager 示例中,如果我們想把事件日期傳遞到 native,我們必須將它轉(zhuǎn)換成一個(gè)字符串或一個(gè)數(shù)字:

    - (void)addEventWithName:(NSString *)name location:(NSString *)location date:(NSInteger)secondsSinceUnixEpoch
    {
        RCT_EXPORT(addEvent);
        NSDate *date = [NSDate dateWithTimeIntervalSince1970:secondsSinceUnixEpoch];
    }

隨著 CalendarManager.addEvent 方法變得越來(lái)越復(fù)雜,參數(shù)的數(shù)量將會(huì)增加。其中一些可能是可選的。在這種情況下對(duì)改變 API 一點(diǎn)來(lái)接受事件屬性的字典是值得考慮的,如:

    #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 沒(méi)有為這些結(jié)構(gòu)中值的類型提供任何擔(dān)保。你的 native 模塊可能期望一個(gè)字符串?dāng)?shù)組,但如果 JavaScript 調(diào)用你的包含數(shù)字和字符串?dāng)?shù)組的方法,你會(huì)得到帶有 NSNumberNSStringNSArray。檢查數(shù)組/映射值類型是開(kāi)發(fā)人員的責(zé)任 (助手方法見(jiàn) RCTConvert)。

回調(diào)

警告

本節(jié)比其他更具有實(shí)驗(yàn)性,圍繞回調(diào)我們沒(méi)有得到一組最佳實(shí)踐。

Native 模塊還支持一種特殊的參數(shù)——回調(diào)。在大多數(shù)情況下它是用來(lái)向 JavaScript 提供函數(shù)調(diào)用結(jié)果的。

    - (void)findEvents:(RCTResponseSenderBlock)callback
    {
        RCT_EXPORT();
        NSArray *events = ...
        callback(@[[NSNull null], events]);
    }

RCTResponseSenderBlock 只接受一個(gè)參數(shù)——參數(shù)的數(shù)組傳遞給 JavaScript 的回調(diào)。在本例中,我們使用節(jié)點(diǎn)的慣例來(lái)為 error 和其他的——函數(shù)的結(jié)果設(shè)置第一個(gè)參數(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 存儲(chǔ)并稍后調(diào)用回調(diào)。這種模式通常用于包裝需要委托的 iOS 的 APIs。請(qǐng)看 RCTAlertManager。

如果你想向 JavaScript 傳遞 error ——如對(duì)象,使用 RCTUtils.hRCTMakeError

實(shí)現(xiàn) native 模塊

Native 模塊應(yīng)該沒(méi)有任何關(guān)于什么線程正在被調(diào)用的假設(shè)。React Native 在一個(gè)單獨(dú)的串行 GCD 隊(duì)列中調(diào)用 native 模塊方法,但這是一個(gè)實(shí)現(xiàn)細(xì)節(jié),可能會(huì)改變。如果 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(@[...]);
  });
}

同樣的方法,如果操作要很長(zhǎng)時(shí)間才能完成,native 模塊不應(yīng)該阻塞。使用 dispatch_async 在后臺(tái)隊(duì)列中安排耗費(fèi)大的工作是一個(gè)好主意。

導(dǎo)出常量

Native 模塊可以在運(yùn)行時(shí)向 JavaScript 導(dǎo)出立即可用的常量。導(dǎo)出一些初始數(shù)據(jù)是有用的,否則這些初始數(shù)據(jù)需要往返的橋梁。

- (NSDictionary *)constantsToExport
{
  return @{ @"firstDayOfTheWeek": @"Monday" };
}

JavaScript 能夠立即使用這些值:

console.log(CalendarManager.firstDayOfTheWeek);

注意,只有在初始化時(shí)常量才能被導(dǎo)出,所以如果你在運(yùn)行時(shí)改變了 constantsToExport 的值,它不會(huì)影響 JavaScript 環(huán)境。

發(fā)送事件到 JavaScript

Native 模塊可以在不被直接調(diào)用的情況下向 JavaScript 發(fā)送事件信號(hào)。最簡(jiǎn)單的方法是使用 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}];
    }
    @end

JavaScript 代碼可以訂閱這些事件:

var subscription = DeviceEventEmitter.addListener(
  'EventReminder',
  (reminder) => console.log(reminder.name)
);
...
// Don't forget to unsubscribe
subscription.remove();

更多的向 JavaScript 發(fā)送事件的例子,請(qǐng)看 RCTLocationObserver。