FlutterからSwiftのネイティブコードを呼び出す。

##背景
仕事でFlutterを触る機会があり、自分の備忘録として残しておきたいと思います。
今回はSwiftのImagePickerControllerをFlutter側から呼び出す手順になります。

##内容
サンプルとしてファイルを作成します。

```
flutter create -i swift my_app
```


作成したフォルダを開くと**lib/main.dart**があるので開きます。
以下は、かなり省略していますが、全体のイメージです。

```lib/main.dart
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

​class _MyHomePageState extends State<MyHomePage> {
  static const platform = const MethodChannel('test_camera');

  Future<void> _getCamera() async {
    String cameraLevel;
    try {
      await platform.invokeMethod('getCamera');
    } on PlatformException catch (e) {
      cameraLevel = "Failed to get camera";
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'Camera List!',
            ),
            RaisedButton(
            child: Text('Get Camera'),
            onPressed: _getCamera,
            ),
          ],
        ),
      ),
    );
  }
}
```


まずは、SwiftとFlutterを結ぶためのチャンネルを作成します。
チャンネルを作成することでやり取りを可能にします。

```
static const platform = const MethodChannel('test_camera');
```

Swift側にも設定をします。

```ios/Runner/AppDelegate.swift
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
    
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?

  ) -> Bool {
    let controller :FlutterViewController = window?.rootViewController as! FlutterViewController
    let cameraChannel = FlutterMethodChannel(name: "test_camera",
                                             binaryMessenger: controller.binaryMessenger)
    
}

```

チャンネルを繋げたら次にSwift側のメソッドを呼び出すための準備をします。
以下のRaisedButtonを押すと、_getCamera()メソッドが呼ばれます。
_getCameraの**await platform.invokeMethod('getCamera');**でSwift側にメッセージを送ります。

```lib/main.dart
Future<void> _getCamera() async {
    String cameraLevel;
    try {
     //Swiftにメッセージ 'getCamera'を送る
      await platform.invokeMethod('getCamera');
    } on PlatformException catch (e) {
      cameraLevel = "Failed to get camera";
    }
  }


@override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          children: <Widget>[
            Text(
              'Camera List!',
            ),
            RaisedButton(
            child: Text('Get Camera'),
            onPressed: _getCamera,
            ),
          ],
        ),
      ),
    );
  }

```

_getCameraメソッドで送ったメッセージをSwift側で受け取ります。
あとはネイティブ側で自分で作成したメソッドを呼び出せば完了です。

```ios/Runner/AppDelegate.swift
 cameraChannel.setMethodCallHandler({
      (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
        switch call.method {
        case "getCamera":
          self.receiveCamera(result: result,controller: controller)
        default:
          result(FlutterMethodNotImplemented)
          return
        }
    })

 func receiveCamera(result: FlutterResult,controller: FlutterViewController) {
        let pickerController = UIImagePickerController()
        pickerController.sourceType = .camera
        
        controller.present(pickerController,animated: true,completion: nil)
    }

```

殴り書きで見にくいとは思いますが、ご了承ください。
flutter側からネイティブコードを呼び出す記事が少なかったので、共有させていただきます。
誰かの役に立てたら光栄です。

ちなみに**Info.plistファイル**にカメラの許可する設定もお忘れなく。。。
<img width="346" alt="スクリーンショット 2019-10-29 22.52.30.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438198/8667866e-1df1-767c-afe0-99239f4ca7ec.png">

以上です。