Home > Mobile >  Flutter plugin - MethodChannel: .invokeMethod() from native iOS to Flutter never reaches Flutter par
Flutter plugin - MethodChannel: .invokeMethod() from native iOS to Flutter never reaches Flutter par

Time:08-22

I'm having an issue with Flutter plugin development, especially with invoking MethodChannel from native iOS side to trigger Flutter plugin code. On Android, identical (in terms of logic) code described further works perfectly for both sides (calling from Android / calling from Flutter).

On iOS, I can successfully receive Flutter method calls on native iOS side, but never receive corresponding method calls from native iOS side in Dart plugin code. This is true for iPhone 11(iOS 15.6.1), iPhone X(iOS 15.5) and variety of latest iOS simulators I tried within my environment.

I use VSCode/xCode for developing the iOS side of the plugin. I've tried to downgrade Flutter version (3.0.5 -> 2.10.3), update/downgrade xCode, clean xCode derived data, reboot hardware etc.

I've created plugin with common template flutter create --org com.mycompany --template=plugin --platforms=android,ios t_plugin.

I'm using autogenerated plugin_platform_interface: ^2.0.2 (tried 2.1.2) and noticed that the package itself has not beed updated for a while (about 7 months).

There is a similar issue Flutter MethodChannel from iOS to Native not working which looks really bizarre in terms of possible workarounds (none of which worked for me).

Any similar experience description will be appreciated.


Expected results:

  • methodCall.method in methodChannel.setMethodCallHandler((methodCall) async { ... } is being triggered (or at least visible while debugging within Dart plugin)
  • result(r) in self.channel!.invokeMethod("onFinish", arguments: nil, result: {(r:Any?) -> () in ... }) is being triggered (or at least visible while debugging within iOS native plugin)

Actual results: No signs of triggering the Dart method call handler while invoking native channel method from iOS (no logs/triggers on any side).


Code samples

Swift:

import Flutter
import UIKit

public class SwiftTPlugin: NSObject, FlutterPlugin, FlutterApplicationLifeCycleDelegate {

    private var channel: FlutterMethodChannel? = nil

    public static func register(with registrar: FlutterPluginRegistrar) {
        let channel = FlutterMethodChannel(name: "f_plugin_test", binaryMessenger: registrar.messenger())
        let instance = SwiftTestPlugin()
        instance.channel = channel
        registrar.addMethodCallDelegate(instance, channel: channel)
        registrar.addApplicationDelegate(instance)
    }

    public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
         // Method call handling from Flutter side is working fine
    }

    public func finish() {
        if (self.channel == nil) {
               print("CHANNEL IS NIL!");  // Never comes here, which means channel should be valid and is existing
         } else {
            print("CHANNEL IS _NOT_ NIL");  // Prints
         }

          //Tried shorter method implementations - result is the same
          self.channel!.invokeMethod("onFinish", arguments: "TEST", result: {(r:Any?) -> () in
                 print(r.debugDescription);  // Never comes here
          })
     }
 

Dart:

import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:t_flutter/t_flutter.dart';
import 't_flutter_platform_interface.dart';
  
 const methodChannel = MethodChannel("f_plugin_test");

 /// An implementation of [VcheckFlutterPlatform] that uses method channels.
 class MethodChannelTFlutter extends TFlutterPlatform {

  @override
  void start() {
     methodChannel.setMethodCallHandler((methodCall) async {
       debugPrint("CAUGHT METHOD WITH HANDLER: ${methodCall.method}");  // Never comes here
       switch (methodCall.method) {
         case "onFinish":
           debugPrint("onFinish"); // Never comes here
           return;
         default:
           throw MissingPluginException('Not Implemented'); // Never comes here
       }
     });
 }

flutter doctor summary:

Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.0.5, on macOS 12.1 21C52 darwin-x64, locale
    uk-UA)
[✓] Android toolchain - develop for Android devices (Android SDK version
    32.0.0-rc1)
[✓] Xcode - develop for iOS and macOS (Xcode 13.4.1)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2021.2)
[✓] VS Code (version 1.70.2)
[✓] Connected device (3 available)
[✓] HTTP Host Availability

CodePudding user response:

So, the reason of described behavior itself (in my particular case) was definitely in changing root view controller from FlutterViewController to my custom iOS UIViewController (reason - plugin had a reference to native SDK which used its own storyboard).

Seems there wasn't any feature request yet to clarify that inconvenience for native iOS plugin users in documentation/readme.

  • Related