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 的通信就容易多了。

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

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

相关推荐
kyriewen25 分钟前
你的代码仓库变成“毛线团”了?Monorepo 用 Turborepo 拆成“乐高积木”
前端·javascript·面试
身如柳絮随风扬28 分钟前
你知道什么是 Ajax 吗?—— 从入门到原理,一篇彻底搞懂
前端·ajax·okhttp
旷世奇才李先生1 小时前
Vue3\+TypeScript 2026实战——企业级前端项目架构搭建与性能优化全指南
前端·架构·typescript
Beginner x_u1 小时前
前端八股整理(工程化 02)|CommonJS/ESM、Webpack Loader/Plugin 与Vite 对比
前端·webpack·node.js·plugin·loader
openKaka_2 小时前
createRoot 到底创建了什么:FiberRootNode 和 HostRootFiber 的初始化过程
前端·javascript·react.js
习明然2 小时前
UniApp开发体验感受总结
前端·uni-app
刀法如飞3 小时前
Claude Code Skills 推荐:2026年最值得安装的10个AI技能
前端·后端·ai编程
Lee川3 小时前
面试手写 KeepAlive:React 组件缓存的实现原理
前端·react.js·面试
墨染天姬4 小时前
【AI】cursor提示词小技巧
前端·数据库·人工智能
烛阴4 小时前
TEngine 入门系列(一):TEngine 是什么 & 为什么选它
前端·unity3d