Search code examples
iosswiftflutterflutter-platform-channel

How to handle platform thread without plugin in Flutter from native iOS?


Since Flutter 3.13 you may have noticed new Flutter errors according your platform channel method invocation (iOS) :

[ERROR:flutter/shell/common/shell.cc(1015)] The 'CameraController' channel sent a message from native to Flutter on a non-platform thread. Platform channel messages must be sent on the platform thread. Failure to do so may result in data loss or crashes, and must be fixed in the plugin or application code creating that channel.
See https://docs.flutter.dev/platform-integration/platform-channels#channels-and-platform-threading for more information.

Inside the doc, the only example to implement a TaskQueue to handle the multi-thread is written for a plugin concept :

public static func register(with registrar: FlutterPluginRegistrar) {
  let taskQueue = registrar.messenger.makeBackgroundTaskQueue()
  let channel = FlutterMethodChannel(name: "com.example.foo",
                                     binaryMessenger: registrar.messenger(),
                                     codec: FlutterStandardMethodCodec.sharedInstance,
                                     taskQueue: taskQueue)
  let instance = MyPlugin()
  registrar.addMethodCallDelegate(instance, channel: channel)
}

However I'm not using plugins for my iOS channels, I have initialized them all inside the AppDelegate like this :

let flutterController : FlutterViewController = window?.rootViewController as! FlutterViewController                    
let cameraChannel = FlutterMethodChannel(name: "CameraController", binaryMessenger: flutterController.binaryMessenger)

Then I'm calling from my native iOS channel at app start :

private func setupCameraConst() {
 DispatchQueue.main.async {
  channel!.invokeMethod("setAspectRatio", arguments: aspectRatio)
  channel!.invokeMethod("setMinZoomLevel", arguments: minZoom)
  channel!.invokeMethod("setMaxZoomLevel", arguments: maxZoom)
  channel!.invokeMethod("setMinExposure", arguments: minExposure)
  channel!.invokeMethod("setMaxExposure", arguments: maxExposure)
  channel!.invokeMethod("setOnFrontCamera", arguments:   cameraPosition == .front)
 }
}

So my question is how to handle the platform thread without using plugin ?


Solution

  • This is addressed in the official platform channel documentation:

    DispatchQueue.main.async {
      // Make your invokeMethod calls here.
    }