Flutter踩坑:原生IOS页面向Flutter通信

Flutter踩坑:原生IOS页面向Flutter通信

前言

Flutter APP 的开发过程中,有时不仅需要使用 Flutter 提供的组件,还需要使用原生的组件。

例如在对接外部 SDK 时,如果自己重新实现 SDK 的逻辑,无疑是本末倒置。

前文中我们已经完成原生安卓向 Flutter 发送信息,那么本篇文章我们来完成iOS原生页面Flutter通信。

操作雷同,就是将 method channel 的调用,反过来,由原生执行 invokeMethod ,由 Flutter 接收 method

iOS相对安卓的调用要更加顺畅一些,但是同样存在 MethodChannel 传递的问题。

执行

在插件中实例化FlutterMethodChannel,并且注册 MethodCallHandler

同时将这个 MethodChannel 放到静态变量中,以便在 objc 页面中调用。

这个我在网上搜了很多方式,都是让实例化 Flutter Engine 或者实例化 plugin 插件,但是实际上都没能成功,估计重新实例化的已经不是当前的这个 Flutter Engine实例或者插件实例了。

objc 代码的方式

c 复制代码
// 省略import
+ (instancetype)sharedInstance {
    static TestPluginIosPlugin *sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[self alloc] init];
    });
    return sharedInstance;
}

- (void)sendMessageToFlutter:(NSString *)message {
    if (message) {
        NSLog(@"Sending message to Flutter: %@", message);
        NSLog(@"self.flutterChannel:::: %@", self.flutterChannel);
        [self.flutterChannel invokeMethod:@"receiveMessageFromiOS" arguments:message];
    } else {
        NSLog(@"Message is nil, cannot send to Flutter.");
    }
}

objc 页面中调用

c 复制代码
[[TestPluginIosPlugin sharedInstance] sendMessageToFlutter:result];

如果是 Swift 的话,直接静态变量调用即可

swift 复制代码
import Flutter
import UIKit

public class IosSdkFlutterPlugin: NSObject, FlutterPlugin {

  // 静态变量
  static var channel: FlutterMethodChannel?

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

Swift中调用

swift 复制代码
import UIKit

class YourViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.backgroundColor = UIColor.white
        let button = UIButton(frame: CGRect(x: 50, y: 100, width: 200, height: 50))
        button.setTitle("Tap Me", for: .normal)
        button.addTarget(self, action: #selector(labelTapped), for: .touchUpInside)
        self.view.addSubview(button)
    }

    @objc func labelTapped(){
      IosSdkFlutterPlugin.channel!.invokeMethod("onMessageReceived", arguments: "your_arguments")
    }
}

Flutter 页面中接收到信息

c 复制代码
MethodChannel("test_plugin").setMethodCallHandler((call) async {
  print("接到方法调用: ${call.method}");
  if (call.method == 'onMessageReceived') {
    final String message = call.arguments as String;
    print('========aaa Received message from IOS: $message');
    // TODO: 处理接收到的信息
  }
});

总结

原生向 Flutter 发送信息时,会遇到许多莫名其妙的问题,网上搜了很多方法,但是都无效。

安卓的调用方式通了过后,再来处理 iOS 的通信就容易多了。

当然,我觉得这个问题应该有更好的解决方案,但是目前没有找到,先使用这个方式解决问题,以作记录。

如果有更好的解决方案的同学欢迎交流。👏🏻

相关推荐
小小小小宇2 分钟前
二维数组按顺时针螺旋顺序
前端
安木夕21 分钟前
C#-Visual Studio宇宙第一IDE使用实践
前端·c#·.net
努力敲代码呀~23 分钟前
前端高频面试题2:浏览器/计算机网络
前端·计算机网络·html
高山我梦口香糖1 小时前
[electron]预脚本不显示内联script
前端·javascript·electron
神探小白牙1 小时前
vue-video-player视频保活成功确无法推送问题
前端·vue.js·音视频
90后的晨仔1 小时前
git 命令汇总
ios
Angel_girl3192 小时前
vue项目使用svg图标
前端·vue.js
難釋懷2 小时前
vue 项目中常用的 2 个 Ajax 库
前端·vue.js·ajax
Qian Xiaoo2 小时前
Ajax入门
前端·ajax·okhttp
爱生活的苏苏2 小时前
vue生成二维码图片+文字说明
前端·vue.js