React NativeのNativeModuleの登録プロセスを追ってみた
参加者
前回の振り返り
- JavaScript側でsetNativePropsが実行され、どのようにNative側に渡される値が作られるかを追い掛けた
- 最終的に、TextInputのpropsを更新した時に、enqueueNativeCallと言うメソッドで積まれている moduleId、 methodId、 params (updatePayload) の値を特定できた
{ moduleID: 41, methodID: 6, params: { // updatePayload fontSize: 40, }, }
ここからわかること
- JavaScript側で、Native側のmoduleIdとmethodIdを知っている
- これどこに持ってる?
- TextInputと言うのは一つのNativeModule?
- TextInputと言うNativeModuleが登録された時に割り当てられたIDがmoduleIdなのでは?
- 登録を行うと、JavaScriptにも、各moduleのIDが渡されている?
今回やっていくこと
- オーバー・ザ・ブリッジ本の、NativeModulesの章を読み進めて、moduleId、methodIdがどう使われているのか突き止める
NativeModule
公式ドキュメントより
https://facebook.github.io/react-native/docs/native-modules-ios#ios-calendar-module-example
上記リンクに、iOSのCalendar APIにアクセスするNativeModuleを作成するための方法が書かれている
NativeModuleを作る方法ざっくりまとめ
- Objective-Cのclassで、
RCTBridgeModule
protocolを実装する - 下記の2つのマクロを使う
- RCT_EXPORT_MODULE()
- RCT_EXPORT_METHOD()
RCT_EXPORT_MODULE()
- moduleの名前を吐き出して、JavaScript側から見えるようにする
RCT_EXPORT_MODULE(HogeManager)
のように呼ぶと、HogeManagerと言う名前でexportされる- 名前を明示的に指定しなければ、class名がそのまま使われる
- 接頭辞として
RCT
がclass名についていれば、省略した状態でexportされる (RCTHogeManager => HogeManager)
RCT_EXPORT_METHOD()
RCT_EXPORT_METHOD(addEvent:(NSString *)name location:(NSString *)location) { RCTLogInfo(@"Pretending to create an event %@ at %@", name, location); }
- methodを吐き出して、JavaScript側から呼べるようにする
- 上記の例では、
addEvent
と言うmethodがexportされ、引数としてnameとlocationの2つを受け取る設定になる - 実行されるmethodの実体は、
{}
の中に書かれ、これをJavaScript側から呼ぶことが出来るようになる - 引数として指定できる型は、基本的に、JSONと相互に変換出来る型のみ
- それ以外は、
RCTConvert
helperを使って変換する
作り方を見てわかったこと
- NativeModuleを登録する時に、moduleとmethodをそれぞれexportしていることはわかった
- TextInputも、同様な方法でNativeModuleとして登録されている?(わからない)
TextInputの継承ツリーを追う
方針
- この中のどこかでTextInputがRCT_EXPORT_MODULEされている?
- であれば、TextInputのmoduleIdとmethodIdが取れるようになり、どこが具体的に呼ばれるのか特定できそう!
- TextInputは
clear
とisFocused
という2つのメソッドをもつので、ネイティブモジュールからexportされているのでは?(以下参照)
https://facebook.github.io/react-native/docs/textinput#methods
見つかったもの
- RCTSinglelineTextInputViewManager : RCTBaseTextInputViewManager
- RCTSinglelineTextInputView : RCTBaseTextInputView
RCT_EXPORT_MODULE
していない
- RCTBaseTextInputView : RCTView
RCT_EXPORT_MODULE
していない
わかったこと
- 全然exportしてない
clear
とisFocused
は、NativeModuleと一切関係なく、普通にJSだけで実装されていた