<link rel="stylesheet" href="https://csdnimg.cn/release/blogv2/dist/mdeditor/css/editerView/kdoc_html_views-1a98987dfd.css">
<link rel="stylesheet" href="https://csdnimg.cn/release/blogv2/dist/mdeditor/css/editerView/ck_htmledit_views-25cebea3f9.css">
<div id="content_views" class="markdown_views prism-atom-one-light">
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path>
</svg>
<p><a href="https://so.csdn.net/so/search?q=flutter&spm=1001.2101.3001.7020" target="_blank" class="hl hl-1" data-report-click="{"spm":"1001.2101.3001.7020","dest":"https://so.csdn.net/so/search?q=flutter&spm=1001.2101.3001.7020","extra":"{\"searchword\":\"flutter\"}"}" data-tit="flutter" data-pretit="flutter">flutter</a>开发实战-MethodChannel实现flutter与iOS双向通信</p>
最近开发中需要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端的参数
代码如下
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(‘KaTeX parse error: Expected 'EOF', got '}' at position 221: …n punctuation">}̲</span> <span c…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);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
使用该MethodChannel,我们需要使用MethodChannel
使用代码如下
void initState() { // TODO: implement initState super.initState();
<span class="token function">setMethodHandle</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
}
void setMethodHandle() {
FlutterMethodChannel.methodHandlerListener((call) {
print(“methodHandlerListener call:KaTeX parse error: Expected '}', got 'EOF' at end of input: …n punctuation">{
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();
}
void dispose() {
// TODO: implement dispose
super.dispose();
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
这里我们处理了方法methodToFlutter来接收iOS端的传参数调用,同时处理后我们将结果"message from flutter"返回给iOS端。
我们调用iOS端的方法methodTest,并且传参,获取iOS端传回的结果。
三、在iOS端实现MethodChannel
在iOS中,同样我们实现了MethodChannel。
iOS实现MethodChannel需要实现FlutterPlugin,实现registerWithRegistrar
我这里命名一个SDFlutterMethodChannelPlugin继承NSObject,通过实现registerWithRegistrar方法
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar { FlutterMethodChannel *methodChannel = [FlutterMethodChannel methodChannelWithName:kFlutterMethodChannelName binaryMessenger:[registrar messenger] codec:[FlutterStandardMethodCodec sharedInstance]];
SDFlutterMethodChannelPlugin <span class="token operator">*</span>instance <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">[</span>SDFlutterMethodChannelPlugin alloc<span class="token punctuation">]</span> initWithMethodChannel<span class="token punctuation">:</span>methodChannel<span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token comment">// 将插件注册为来自Dart端的传入方法调用的接收者 在指定的“ FlutterMethodChannel”上。</span> <span class="token punctuation">[</span>registrar addMethodCallDelegate<span class="token punctuation">:</span>instance channel<span class="token punctuation">:</span>methodChannel<span class="token punctuation">]</span><span class="token punctuation">;</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
同样在插件SDFlutterMethodChannelPlugin中设置setMethodCallHandler及调用Flutter的方法
例如
__weak typeof(self) weakSelf = self;
[self.methodChannel setMethodCallHandler:^(FlutterMethodCall *call, FlutterResult result) {
[weakSelf handleMethodCall:call result:result];
}];
- 1
- 2
- 3
- 4
通过handleMethodCall可以处理方法methodTest处理接收来自flutter的参数,处理后并将结果返回给flutter。
整体代码如下
SDFlutterMethodChannelPlugin.h
#import <Foundation/Foundation.h>
#import <Flutter/Flutter.h>
@class SDFlutterMethodChannelPlugin;
typedef void (^SDFlutterMethodChannelPluginCompletionBlock)(SDFlutterMethodChannelPlugin *plugin);
@interface SDFlutterMethodChannelPlugin : NSObject<FlutterPlugin>
- (instancetype)initWithMethodChannel:(FlutterMethodChannel *)methodChannel;
@end
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
SDFlutterMethodChannelPlugin.m
#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];
<span class="token keyword">self</span><span class="token punctuation">.</span>methodChannel <span class="token operator">=</span> methodChannel<span class="token punctuation">;</span>
__weak <span class="token keyword">typeof</span><span class="token punctuation">(</span><span class="token keyword">self</span><span class="token punctuation">)</span> weakSelf <span class="token operator">=</span> <span class="token keyword">self</span><span class="token punctuation">;</span>
<span class="token punctuation">[</span><span class="token keyword">self</span><span class="token punctuation">.</span>methodChannel setMethodCallHandler<span class="token punctuation">:</span><span class="token operator">^</span><span class="token punctuation">(</span>FlutterMethodCall <span class="token operator">*</span>call<span class="token punctuation">,</span> FlutterResult result<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
<span class="token punctuation">[</span>weakSelf handleMethodCall<span class="token punctuation">:</span>call result<span class="token punctuation">:</span>result<span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token punctuation">[</span><span class="token keyword">self</span> startSendMessageTimer<span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> <span class="token keyword">self</span><span class="token punctuation">;</span>
}
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>)registrar {
FlutterMethodChannel methodChannel = [FlutterMethodChannel methodChannelWithName:kFlutterMethodChannelName binaryMessenger:[registrar messenger] codec:[FlutterStandardMethodCodec sharedInstance]];
SDFlutterMethodChannelPlugin <span class="token operator">*</span>instance <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">[</span>SDFlutterMethodChannelPlugin alloc<span class="token punctuation">]</span> initWithMethodChannel<span class="token punctuation">:</span>methodChannel<span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token comment">// 将插件注册为来自Dart端的传入方法调用的接收者 在指定的“ FlutterMethodChannel”上。</span>
<span class="token punctuation">[</span>registrar addMethodCallDelegate<span class="token punctuation">:</span>instance channel<span class="token punctuation">:</span>methodChannel<span class="token punctuation">]</span><span class="token punctuation">;</span>
}
#pragma mark - FlutterPlugin协议方法
- (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result {
NSLog(@“config handleMethodChannel callmethod:%@,params:%@,result:%@”, call.method, call.arguments, result);
<span class="token comment">// 没有处理,需要单独处理</span>
NSString <span class="token operator">*</span>method<span class="token operator">=</span>call<span class="token punctuation">.</span>method<span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token punctuation">[</span>method isEqualToString<span class="token punctuation">:</span><span class="token string">@"methodTest"</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
<span class="token function">NSLog</span><span class="token punctuation">(</span><span class="token string">@"flutter 调用到了 ios test"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
NSMutableDictionary <span class="token operator">*</span>dic <span class="token operator">=</span> <span class="token punctuation">[</span>NSMutableDictionary dictionary<span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token punctuation">[</span>dic setObject<span class="token punctuation">:</span><span class="token string">@"result.success 返回给flutter的数据"</span> forKey<span class="token punctuation">:</span><span class="token string">@"message"</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token punctuation">[</span>dic setObject<span class="token punctuation">:</span> <span class="token punctuation">[</span>NSNumber numberWithInt<span class="token punctuation">:</span><span class="token number">200</span><span class="token punctuation">]</span> forKey<span class="token punctuation">:</span><span class="token string">@"code"</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token function">result</span><span class="token punctuation">(</span>dic<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token punctuation">[</span>method isEqualToString<span class="token punctuation">:</span><span class="token string">@"test2"</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
<span class="token function">NSLog</span><span class="token punctuation">(</span><span class="token string">@"flutter 调用到了 ios test2"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">result</span><span class="token punctuation">(</span><span class="token operator">@</span>YES<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{<!-- --></span>
<span class="token function">result</span><span class="token punctuation">(</span>FlutterMethodNotImplemented<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
}
#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
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
在iOS中需要在AppDelegate中设置,在- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions方法中实现
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[SDFlutterMethodChannelPlugin registerWithRegistrar:[(id)[SDWeakProxy proxyWithTarget:self] registrarForPlugin:@“SDFlutterMethodChannelPlugin”]];
return YES;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
我们在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
学习记录,每天不停进步。