🧊

React NativeでNativeからのイベントをSwiftで受けて使うには

またも何が言いたいんだみたいなタイトルですがようは、

  • Native側で特定のタイミングでイベント発火
  • それをjs側で監視

それを、Swiftでどう書けばできるようになるのかというメモです。
またもドキュメントにはObj-Cのことしか書いてません。

Native Modules

必要なファイル

これは普通にNativeのブリッジをSwiftで用意したときと一緒で、以下3つ。

  • `XXX.swift`で実装
  • `XXX.m`でエクスポート
  • `MyProject-Bridging-Header.h`でつなぐ

書くまでもないけどエクスポートするのをお忘れなく・・。

`MyProject-Bridging-Header.h`

#import "RCTEventEmitter.h"

イベント用のモジュールをインポートするだけ。

`XXX.swift`

3ステップです。

1. クラスの元をかえる

// @objc(XXX) class XXX: NSObject {}
@objc(XXX) class XXX: RCTEventEmitter {}

といった具合に、`NSObject`を元にしてたのを、`RCTEventEmitter`に変更します。

2. 必要なイベントを定義

override func supportedEvents() -> [String]! {
  return ["onend"]
}

この`supportedEvents`ってのを定義して、発火するイベント名を配列で予め定義しておく必要があるみたい。
コレをサボるとコンパイルでコケます。

3. イベント発火

あとは好きなタイミングで発火するだけ。

self.sendEventWithName("onend", body: "fooooo")

`self`でアクセスするの気持ち悪くて最初は別クラスにしてたけど、なぜかそれだと上手くいかず。
SwiftっていうかReact Nativeが絡んだせいでなんか色々制約があってコケてるんやと思うけどよーわからん!

jsで受ける

import {
  NativeModules,
  NativeEventEmitter,
} from 'react-native';
const myEv = new NativeEventEmitter(NativeModules.XXX);

const subscription = myEv.addListener('onend', (payload) => {
  console.log(JSON.stringify(payload, null, 2));
});

// いらなくなったら
subscription.remove();

もっとSwiftまわりのドキュメント充実させてくれーーーー