サイト名変更・お引越しのお知らせ

【iOS・Swift】React NativeでNative Modulesを実装する方法を解説

React NativeでiOS向けにSwiftを用いて、Native Modulesを実装する方法を解説します。

モグモグさん

出来るだけ分かりやすく解説していきます。

この記事でわかること
  • Native Modulesがわかる
  • Swiftを用いてカスタムのNative Modulesを作成することができる

バージョン
  • React 17.0.2
  • React Native 0.65.1

モグモグさん

Objective-Cで実装する方法についてはこちらで解説しています。

【iOS・Objective-C】React NativeでNative Modulesを実装する方法を解説

Native Modulesとは?

Native Modulesについて簡単に解説します。

モグモグさん

すでに理解している方はスキップしてください。

Native Modulesとは、React Nativeで用意されていない機能をネイティブで実装するための機能です。

アプリの要件によって、React Nativeがもともと用意していない機能を足したり、パフォーマンスの観点等でネイティブで実装すべき箇所をNative Modulesを使って実装したりすることが多いです。

React Nativeでも多くのことがすでにできますが、Native Modulesを使うことで幅が広がります

  • iOS: Objective-CSwiftどちらでも実装可能
  • Android: JavaKotlinどちらでも実装可能

本記事では紹介しませんが、UIに関連するものは、Native UI Componentsを利用します。

モグモグさん

事前準備(ベースのアプリを作成)

まずは、React Nativeでアプリを作成しましょう。

この記事では、NativeModuleExampleというプロジェクトを作成しました。

モグモグさん

すでに作成済みの方はスキップでOKです!

こちらの記事も参考にしてください。

ReactNative 【ReactNative入門 】Macで開発環境を作って始める

Native Modulesの作成

それでは、Native Modulesを作成していきます。

CustomNativeModuleファイルの作成

まずは、Swiftファイルを作成します。

本記事では、CustomNativeModuleSwiftというファイル名にしましたが、任意の名前にしてください。

モグモグさん

次で解説しますが、Objective-C bridging headerを作成しますか?というポップアップが表示される場合は作成してください。

よく使いそうなメソッド + 具体的なメソッドを実装しています。

  • シンプルなメソッド
  • callbackを返すメソッド
  • 引数を取るメソッド
  • Promiseを扱うメソッド
  • OSのバージョンを返すメソッド

モグモグさん

重要なポイントはコメントに記載しているので、確認してください。

import Foundation

// @objc(CustomNativeModuleSwift)の箇所が重要
@objc(CustomNativeModuleSwift) class CustomNativeModuleSwift: NSObject {
  @objc static func requiresMainQueueSetup() -> Bool { return true }
  
  // 出力するだけのメソッド
  @objc public func funcSimple() {
    print("funcSimple")
  }
  
  // callbackメソッド
  @objc public func funcCallback(_ callback: RCTResponseSenderBlock) {
    callback(["funcCallback"])
  }
  
  // 引数を取るcallbackメソッド
  @objc public func funcCallbackWithParams(_ param: String, callback: RCTResponseSenderBlock) {
    callback(["funcCallbackWithParams: '\(param)'"])
  }
  
  // Promise resolveパターンのメソッド
  @objc public func funcResolvePromise(
    _ resolve: RCTPromiseResolveBlock,
    rejecter reject: RCTPromiseRejectBlock
    ) {
    resolve("funcResolvePromise")
  }
  
  // Promise rejectパターンのメソッド
  @objc public func funcRejectPromise(
    _ resolve: RCTPromiseResolveBlock,
    rejecter reject: RCTPromiseRejectBlock
  ) {
    reject("error", "funcRejectPromise", nil)
  }
  
  // 実用例: デバイスの名前を返すメソッド
  @objc public func getDeviceName(
      _ callback: RCTResponseSenderBlock
    ) {
    callback([UIDevice.current.name])
    }
}

Objective-C Bridging headerを作成

続いてObjective-C bridging headerを作成します。

import <React/RCTBridgeModule.hを追加するだけですが、忘れないようにしましょう。

#import <React/RCTBridgeModule.h>

Objective-Cファイルを作成しJavaScriptから使えるようにする

続いて、Objective-Cのファイルを作成して、JavaScriptから定義したModuleとメソッドを使えるようにしていきます。

  • RCT_EXTERN_MODULE: Moduleを記載
  • RCT_EXTERN_METHOD: メソッドを記載

#import "React/RCTBridgeModule.h"

@interface RCT_EXTERN_MODULE(CustomNativeModuleSwift, NSObject)
  RCT_EXTERN_METHOD(getDeviceName:
    (RCTResponseSenderBlock) callback
  )
  RCT_EXTERN_METHOD(funcSimple)
  RCT_EXTERN_METHOD(funcCallback:
    (RCTResponseSenderBlock) callback
  )
  RCT_EXTERN_METHOD(funcCallbackWithParams:
    (NSString *) param
    callback: (RCTResponseSenderBlock)callback
  )
  RCT_EXTERN_METHOD(
    funcResolvePromise: (RCTPromiseResolveBlock) resolve
    rejecter: (RCTPromiseRejectBlock) reject
  )
  RCT_EXTERN_METHOD(funcRejectPromise:
    (RCTPromiseResolveBlock) resolve
    rejecter: (RCTPromiseRejectBlock) reject
  )
@end

JavaScript側から使う

カスタムのNative Modulesを作成したので、JavaScript側から使う方法を解説していきます。

App.jsでimport

Moduleの名前は、ご自身で定義したものを使ってください。

import {NativeModules} from 'react-native';

const App = () => {
  const {CustomNativeModuleSwift} = NativeModules;
}

各メソッドを呼ぶ

呼ぶ場所は、任意ですが本記事では、useEffect内でそれぞれのメソッドを呼んでみました。

const App = () => {
  useEffect(() => {
    CustomNativeModuleSwift.getDeviceName(name => {
      console.log(name);
    });
    CustomNativeModuleSwift.funcSimple();
    CustomNativeModuleSwift.funcCallback(result => {
      console.log(result);
    });
    CustomNativeModuleSwift.funcCallbackWithParams('test', (result, param) => {
      console.log(result, param);
    });

    (async () => {
      const result = await CustomNativeModuleSwift.funcResolvePromise();
      console.log(result);
    })();

    (async () => {
      try {
        await CustomNativeModuleSwift.funcRejectPromise();
      } catch (err) {
        console.error(err);
      }
    })();

  }, []);
}

実行結果

実行結果

実装したModuleのメソッドがそれぞれ呼ばれていることが分かりますね。

まとめ

モグモグさん

お疲れ様でした!

iOS向けにSwiftを用いて、NativeModulesを実装する方法を解説しました。

React Nativeを実装する上で非常に有用なので、ぜひ実際に使ってみてください!