🛠️

[Flutter] UIViewControllerを閉じた後にFlutterで処理を行う方法

2024/08/19に公開

Flutterアプリケーションで、MethodChannelを使用してiOSネイティブのUIViewControllerを表示する処理を実装することがあります。この記事では、そのネイティブ画面が閉じられたときにFlutter側で特定の処理を行う方法について解説します。

前提条件

  • FlutterからiOSネイティブのUIViewControllerを表示する処理が実装済みであること
  • Swiftを使用していること
  • とりあえず私がiOS/FlutterのエンジニアなのでiOS側だけです

iOSネイティブ側の実装 (Swift)

まず、iOSネイティブ側でUIViewControllerが閉じられたときにFlutterへ通知するための実装を行います。

YourViewController.swift

YourViewControllerクラスで、viewDidDisappearメソッドをオーバーライドし、画面が閉じられたことをFlutterに通知します。

YourViewController.swift
import UIKit
import Flutter

class YourViewController: UIViewController {

    var methodChannel: FlutterMethodChannel?

    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        
        // Flutterに通知する
        methodChannel?.invokeMethod("nativeViewDismissed", arguments: nil)
    }
}

AppDelegate.swift

AppDelegate.swiftでは、FlutterのMethodChannelを設定し、YourViewControllerにそのチャンネルを渡します。

AppDelegate.swift
import UIKit
import Flutter

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
    
    override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
        let methodChannel = FlutterMethodChannel(name: "your_channel_name",
                                                 binaryMessenger: controller.binaryMessenger)
        
        let yourViewController = YourViewController()
        yourViewController.methodChannel = methodChannel

        methodChannel.setMethodCallHandler { (call, result) in
            if call.method == "showNativeView" {
                controller.present(yourViewController, animated: true, completion: nil)
                result(nil)
            }
        }

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

Flutter側の実装

Flutter側では、MethodChannelでiOSネイティブからの通知を受け取り、処理を行います。

main.dart

以下のコードでは、ネイティブのUIViewControllerが閉じられたときにコンソールにメッセージを表示する処理を実装しています。

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

class MyHomePage extends StatefulWidget {
  
  _MyHomePageState createState() => _MyHomePageState();
}

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

  
  void initState() {
    super.initState();
    platform.setMethodCallHandler((call) async {
      if (call.method == "nativeViewDismissed") {
        // ネイティブビューが閉じられたときの処理
        print("Native view was dismissed");
      }
    });
  }

  void _showNativeView() {
    platform.invokeMethod('showNativeView');
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Flutter Native Communication"),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: _showNativeView,
          child: Text("Show Native View"),
        ),
      ),
    );
  }
}

まとめ

この手法を使用することで、Flutterアプリケーション内でiOSネイティブのUIViewControllerを表示し、その画面が閉じられたときにFlutter側で任意の処理を実行することができます。
MethodChannelを活用することで、Flutterとネイティブコード間の柔軟な連携が可能になります。

このアプローチは、例えば、ユーザーがネイティブ画面での操作を完了した後に、Flutter側での画面更新やデータリフレッシュを行うシナリオに役立ちます。

補足

この記事はだいたいChatGPT4を使いながら書かれています。
invokeMethodを使った処理は書いてたので、setMethodCallHandlerを使えばキャッチできるって話でしたね。

Discussion