flutter开发实战-MethodChannel实现flutter与iOS双向通信

flutter开发实战-MethodChannel实现flutter与iOS双向通信

最近开发中需要iOS与flutter实现通信,这里使用的MethodChannel

如果需要flutter与Android实现双向通信,请看
https://blog.csdn.net/gloryFlow/article/details/132218837

这部分与https://blog.csdn.net/gloryFlow/article/details/132218837中的一致,这里实现一下iOS端的MethodChannel设置。

一、MethodChannel

MethodChannel:用于传递方法调用(method invocation)。

通道的客户端和宿主端通过传递给通道构造函数的通道名称进行连接

一个应用中所使用的所有通道名称必须是唯一的

使用唯一的域前缀为通道名称添加前缀,比如:samples.flutter.dev/battery

官网 https://flutter.cn/docs/development/platform-integration/platform-channels

二、在flutter端实现MethodChannel

我们需要创建一个名字为"samples.flutter.dev/test"的通道名称。

通过invokeNativeMethod与setMethodCallHandler来实现

invokeNativeMethod:调用Android端的代码

setMethodCallHandler:设置方法回调,用于接收Android端的参数

代码如下

dart 复制代码
import 'package:flutter/services.dart';

//MethodChannel
const methodChannel = const MethodChannel('samples.flutter.dev/test');

class FlutterMethodChannel {
  /*
 * MethodChannel
 * 在方法通道上调用方法invokeMethod
 * methodName 方法名称
 * params 发送给原生的参数
 * return数据 原生发给Flutter的参数
 */
  static Future<Map> invokeNativeMethod(String methodName,
      [Map? params]) async {
    var res;
    try {
      if (params == null) {
        res = await methodChannel.invokeMethod('$methodName');
      } else {
        res = await methodChannel.invokeMethod('$methodName', params);
      }
    } catch (e) {
      res = {'Failed': e.toString()};
    }
    return res;
  }

  /*
 * MethodChannel
 * 接收methodHandler
 * methodName 方法名称
 * params 发送给原生的参数
 * return数据 原生发给Flutter的参数
 */
  static void methodHandlerListener(Future<dynamic> Function(MethodCall call)? handler) {
    methodChannel.setMethodCallHandler(handler);
  }
}

使用该MethodChannel,我们需要使用MethodChannel

使用代码如下

dart 复制代码
  @override
  void initState() {
    // TODO: implement initState
    super.initState();

    setMethodHandle();
  }

  void setMethodHandle() {
    FlutterMethodChannel.methodHandlerListener((call) {
      print("methodHandlerListener call:${call.toString()}");
      if ("methodToFlutter" == call.method) {
        print("methodToFlutter arg:${call.arguments}");
      }
      return Future.value("message from flutter");
    });
  }

  Future<void> invokeNativeMethod() async {
    var result = await FlutterMethodChannel.invokeNativeMethod("methodTest", {"param":"params from flutter"});
    print("invokeNativeMethod result:${result.toString()}");
  }

  void testButtonTouched() {
    invokeNativeMethod();
  }

  @override
  void dispose() {
    // TODO: implement dispose
    super.dispose();
  }

这里我们处理了方法methodToFlutter来接收iOS端的传参数调用,同时处理后我们将结果"message from flutter"返回给iOS端。

我们调用iOS端的方法methodTest,并且传参,获取iOS端传回的结果。

三、在iOS端实现MethodChannel

在iOS中,同样我们实现了MethodChannel。

iOS实现MethodChannel需要实现FlutterPlugin,实现registerWithRegistrar

我这里命名一个SDFlutterMethodChannelPlugin继承NSObject,通过实现registerWithRegistrar方法

objectivec 复制代码
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
    FlutterMethodChannel *methodChannel = [FlutterMethodChannel methodChannelWithName:kFlutterMethodChannelName binaryMessenger:[registrar messenger] codec:[FlutterStandardMethodCodec sharedInstance]];
        
    SDFlutterMethodChannelPlugin *instance = [[SDFlutterMethodChannelPlugin alloc] initWithMethodChannel:methodChannel];
    
    // 将插件注册为来自Dart端的传入方法调用的接收者 在指定的" FlutterMethodChannel"上。
    [registrar addMethodCallDelegate:instance channel:methodChannel];
}

同样在插件SDFlutterMethodChannelPlugin中设置setMethodCallHandler及调用Flutter的方法

例如

objectivec 复制代码
__weak typeof(self) weakSelf = self;
        [self.methodChannel setMethodCallHandler:^(FlutterMethodCall *call, FlutterResult result) {
            [weakSelf handleMethodCall:call result:result];
        }];

通过handleMethodCall可以处理方法methodTest处理接收来自flutter的参数,处理后并将结果返回给flutter。

整体代码如下

SDFlutterMethodChannelPlugin.h

objectivec 复制代码
#import <Foundation/Foundation.h>
#import <Flutter/Flutter.h>

@class SDFlutterMethodChannelPlugin;

typedef void (^SDFlutterMethodChannelPluginCompletionBlock)(SDFlutterMethodChannelPlugin *plugin);

@interface SDFlutterMethodChannelPlugin : NSObject<FlutterPlugin>

- (instancetype)initWithMethodChannel:(FlutterMethodChannel *)methodChannel;

@end

SDFlutterMethodChannelPlugin.m

objectivec 复制代码
#define kFlutterMethodChannelName @"samples.flutter.dev/test"


@interface SDFlutterMethodChannelPlugin ()<FlutterStreamHandler>

@property (nonatomic, strong) FlutterMethodChannel *methodChannel;

@property (nonatomic, strong) NSTimer *sendMessageTimer;


@end

@implementation SDFlutterMethodChannelPlugin

- (instancetype)initWithMethodChannel:(FlutterMethodChannel *)methodChannel {
    self = [super init];
    if (self) {
        self.flutterBridgeConfig = [[DFFlutterBridgeConfig alloc] init];
                
        self.methodChannel = methodChannel;
        __weak typeof(self) weakSelf = self;
        [self.methodChannel setMethodCallHandler:^(FlutterMethodCall *call, FlutterResult result) {
            [weakSelf handleMethodCall:call result:result];
        }];
        [self startSendMessageTimer];
    }
    return self;
}

+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
    FlutterMethodChannel *methodChannel = [FlutterMethodChannel methodChannelWithName:kFlutterMethodChannelName binaryMessenger:[registrar messenger] codec:[FlutterStandardMethodCodec sharedInstance]];
        
    SDFlutterMethodChannelPlugin *instance = [[SDFlutterMethodChannelPlugin alloc] initWithMethodChannel:methodChannel];
    
    // 将插件注册为来自Dart端的传入方法调用的接收者 在指定的" FlutterMethodChannel"上。
    [registrar addMethodCallDelegate:instance channel:methodChannel];
}

#pragma mark - FlutterPlugin协议方法
- (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result {
    NSLog(@"config handleMethodChannel callmethod:%@,params:%@,result:%@", call.method, call.arguments, result);
    
    // 没有处理,需要单独处理
    NSString *method=call.method;
    if ([method isEqualToString:@"methodTest"]) {
        
        NSLog(@"flutter 调用到了 ios test");
        NSMutableDictionary *dic = [NSMutableDictionary dictionary];
        [dic setObject:@"result.success 返回给flutter的数据" forKey:@"message"];
        [dic setObject: [NSNumber numberWithInt:200] forKey:@"code"];

        result(dic);
        
    } else if ([method isEqualToString:@"test2"]) {
        NSLog(@"flutter 调用到了 ios test2");
        result(@YES);
    } else {
        result(FlutterMethodNotImplemented);
    }
}

#pragma mark - 开启定时器
- (void)sendMessageTimerAction {
    // 开启
    [self.methodChannel invokeMethod:@"methodToFlutter" arguments:@"Params from Android"];
}

/**
 开启定时器
*/
- (void)startSendMessageTimer {
    if (_sendMessageTimer) {
        return;
    }
    //开始其实就是开始定时器
    _sendMessageTimer = [NSTimer timerWithTimeInterval:6 target:self selector:@selector(sendMessageTimerAction) userInfo:nil repeats:YES];
    //加到runloop
    [[NSRunLoop currentRunLoop] addTimer:_sendMessageTimer forMode:NSRunLoopCommonModes];
}

/**
 结束定时器
 */
- (void)stopSendMessageTimer {
    //暂停其实就是销毁计时器
    [_sendMessageTimer invalidate];
    _sendMessageTimer = nil;
}

@end

在iOS中需要在AppDelegate中设置,在- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions方法中实现

objectivec 复制代码
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
	
[SDFlutterMethodChannelPlugin registerWithRegistrar:[(id)[SDWeakProxy proxyWithTarget:self] registrarForPlugin:@"SDFlutterMethodChannelPlugin"]];

return YES;
}
    

我们在iOS代码中实现MethodChanel,通过定时器NSTimer定时调用方法methodToFlutter将参数传递给Flutter端。通过在iOS端setMethodCallHandler根据方法methodTest处理接收来自flutter的参数,处理后并将结果返回给flutter。

四、小结

flutter开发实战-MethodChannel实现flutter与iOS双向通信。实现MethodChannel在flutter端与iOS端实现相互通信功能。

https://blog.csdn.net/gloryFlow/article/details/132240415

学习记录,每天不停进步。

相关推荐
黑化旺仔19 小时前
【OC】Runtime:类元数据、加载初始化与消息派发
开发语言·macos·ios·objective-c
songgeb19 小时前
iOS App支持设置RTL语言的实践
ios·swift·ui kit
软泡芙20 小时前
【iOS】swift启动屏显示黑屏
ios
用户69371750013841 天前
当你向领导申请 AI 编程工具预算时,如果领导追问“能提效多少,有量化数据吗”,你该怎么回答?
android·后端·ios
Layer1 天前
一些脱离 Mac 依赖的 Agent 操作 iPhone 实现
ios·ai编程·测试
用户69371750013841 天前
当我说 Claude 搭配 GLM-5.3-Flash 太好用了,同事却提醒我:你可能正在失去对代码的掌控
android·后端·ios
喵个咪1 天前
GoWind ShortPlay 拆解:Flutter 沉浸式 Feed 的播放器工程——生命周期、手势状态机与游客降级
前端·flutter·架构
茶底世界之下1 天前
一键裁方会丢掉什么?用 Awaking 给园林照片做两种画幅
ios
Marco_Marco1351 天前
定位SDK接入实战:Android/iOS/鸿蒙三端怎么选、怎么接
android·ios·harmonyos
老李IT笔记2 天前
关掉设备上的 AI 扩展:两个键各管一层,配错了等于没配
人工智能·ios·智能手机