Xcode
iOS
Flutter

Flutterでネイティブで作ったViewControllerを呼び出す

Flutterではチャンネルという概念を用いてネイティブAPIやネイティブコードを呼び出すことができます。

今回はXcode上で作ったViewControllerをFlutterから呼び出してみたいと思います。

公式ドキュメントではバッテリー情報を取得しています。
https://flutter.io/platform-channels/

チャンネルを設定

まずはFlutter側の設定を書いていきます。

MethodChannel channel =
      const MethodChannel('jp.groupsnap/SandBoxViewController');

設定はこんな感じ。
jp.group.... のところはiOSのネイティブ側と同じ文字列を設定する必要があります。

ネイティブコードを呼ぶ

チャンネルを設定したら呼び出したい箇所で下記のコードを実行します

_callViewController() async {
    try {
      await channel.invokeMethod('callViewController');
    } on PlatformException catch (e) {
      print(e);
    }
  }

callViewController はプラットフォーム側にメッセージを渡せます。
渡すことはなくてもとりあえずなにからテキストを設定しないといけないっぽいです。(?)
(ここの真相はよくわからないのでわかる方教えてください、、、)

AppDelegateにChannelを設定する

import UIKit
import Flutter

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?
  ) -> Bool {
    GeneratedPluginRegistrant.register(with: self)

    // Channelの設定
    setiOSChannel()

    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }

こんなコードを書いて、 setiOSChannel にチャンネル設定の実装を書いていきます。

    func setiOSChannel() {
        // iosチャンネル
        let controller : FlutterViewController = window?.rootViewController as! FlutterViewController;

        // SandboxViewController
        let callSandboxChannel = FlutterMethodChannel.init(name: "jp.groupsnap/SandBoxViewController", binaryMessenger: controller)
        callSandboxChannel.setMethodCallHandler({
            (call, result) -> Void in

            let next = controller.storyboard?.instantiateViewController(withIdentifier: "SandboxViewController")
            controller.present(next!,animated: true, completion: nil)
        })
    }

あとは setMethodCallHandler の中でiOSの画面遷移の実装にしたがって実装を書いていきます。
NavigationControllerで使っていろいろしたりしたかったら window?.rootViewController とかからNavigationControllerを取得(?)してPushViewControllerとかしてください。

雑談

今回はiOSの方を書いていきましたが、Androidの方だとたぶん Intent 投げたりするのかも。
たぶん実装方法はあまり変わらないと思います。