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

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

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

相关推荐
好的佩奇31 分钟前
蓝牙之广播与扫描
android·flutter·蓝牙
卸任2 小时前
Vibe coding工具使用心得
前端·ai编程
wuxianda10303 小时前
2026 苹果审核 4.3 (a) 被拒全解析|Guideline 4.3a spam 马甲包拒审原因 + 避坑方案
flutter·uni-app·苹果上架
brien93 小时前
为什么模型标称 1M,Google Antigravity 聊到 256K 却突然失忆?我们给它做了个原生行内监控圆环
前端
修炼的dance3 小时前
录屏关键帧间隔多少合适?六档实测,2秒到10秒小了75.6%
前端
Lank_M3 小时前
关键帧从1秒拉到10秒,录屏小87.3%,摄像头小10.8%
前端
补码缩写3 小时前
用 ffprobe 拆录屏,八成字节在 29 个关键帧上
前端
百思不得小李3 小时前
一个复杂的动态表单是如何实现的
前端·设计模式
陈随易3 小时前
Cmder 停更 17 个月,2.0 支持 Windows Terminal
前端·后端·程序员
风骏时光牛马4 小时前
前沿视界
前端