iOS與Flutter相互通信
接著上一篇繼續(xù),在原有iOS項(xiàng)目中加入Flutter后,就需要考慮如何通過原生跳轉(zhuǎn)到flutter,如何原生與flutter進(jìn)行通信。
iOS原生跳轉(zhuǎn)Flutter
在ViewController控制器中,添加一個(gè)按鈕--‘flutter跳轉(zhuǎn)’;當(dāng)點(diǎn)擊按鈕的時(shí)候,跳轉(zhuǎn)進(jìn)flutter頁(yè)面。
在跳轉(zhuǎn)的地方,聲明一個(gè)FlutterViewController對(duì)象,然后通過present的方法進(jìn)入flutter頁(yè)面。
具體代碼如下:
#import "ViewController.h"
#import <Flutter/Flutter.h>
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (IBAction)gotoFlutter:(id)sender {
FlutterViewController *flvc = [[FlutterViewController alloc] init];
[self presentViewController:flvc animated:true completion:nil];
}
@end
運(yùn)行演示:

到此最簡(jiǎn)單的原生跳轉(zhuǎn)flutter就完成了。
Flutter返回到原生通信
跳轉(zhuǎn)到Flutter之后,如何回到iOS原生頁(yè)面呢?這個(gè)就涉及到Flutter向原生項(xiàng)目發(fā)送消息。
Flutter向原生通信就需要用到FlutterMethodChannel來(lái)實(shí)現(xiàn),通過FlutterMethodChannel來(lái)為Flutter和原生之間構(gòu)建一座Flutter向原生通信的單向橋梁。
要實(shí)現(xiàn)通信,必須要聲明一個(gè)FlutterMethodChannel:
//單項(xiàng)通信管道,F(xiàn)lutter向原生發(fā)送消息
FlutterMethodChannel *messageChannel = [FlutterMethodChannel methodChannelWithName:@"com.flutterToNative" binaryMessenger:flvc];
然后還要實(shí)現(xiàn)它的回調(diào)函數(shù),才能接收到Flutter給原生發(fā)送的消息:
[messageChannel setMethodCallHandler:^(FlutterMethodCall * _Nonnull call, FlutterResult _Nonnull result) {
//可以在這里實(shí)現(xiàn)flutter發(fā)給原生要實(shí)現(xiàn)的方法
}];
這里只做一種簡(jiǎn)單的,就是flutter告訴原生,要回到原生頁(yè)面。
在flutter里面,利用AppBar上面的leading屬性,加上一個(gè)返回功能,
聲明通信渠道:
//注意這里的com.flutterToNative一定要與原生的名稱相同,不然沒辦法通信
static const methodChannel = MethodChannel('com.flutterToNative');
當(dāng)點(diǎn)擊Flutter里面的返回按鈕時(shí),通過methodChannel來(lái)發(fā)送‘backToNative’消息。
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text('iOS與Flutter交互'),
//點(diǎn)擊返回按鈕時(shí),觸發(fā)消息
leading: IconButton(icon: Icon(Icons.arrow_back_ios), onPressed: ()=>methodChannel.invokeMethod('backToNative')),
),
iOS端只需要在setMethodCallHandler方法里面監(jiān)聽到有消息回調(diào)來(lái)處理就行,需要注意FlutterMethodCall里面的兩個(gè)屬性:
/**
* The method name.方法名稱
*/
@property(readonly, nonatomic) NSString* method;
/**
* The arguments.參數(shù)
*/
@property(readonly, nonatomic, nullable) id arguments;
需要通過解析FlutterMethodCall里面的方法名稱和參數(shù)作出相應(yīng)的操作:
__weak typeof(self) weakSelf = self;
[messageChannel setMethodCallHandler:^(FlutterMethodCall * _Nonnull call, FlutterResult _Nonnull result) {
//通過call.method來(lái)獲取方法名稱
if ([@"backToNative" isEqualToString:call.method]) {
//dismiss掉Flutter控制器,回到原生
[weakSelf dismissViewControllerAnimated:true completion:nil];
}
}];
運(yùn)行代碼演示:

原生發(fā)送消息到Flutter
在跳轉(zhuǎn)到Flutter頁(yè)面的時(shí)候,需要帶一點(diǎn)參數(shù)給Flutter,或者原生需要跳轉(zhuǎn)完Flutter之后,某些數(shù)據(jù)變化的時(shí)候需要給Flutter發(fā)送消息,這個(gè)時(shí)候就需要使用到FlutterEventChannel。
FlutterEventChannel也是一個(gè)單項(xiàng)管道,只能實(shí)現(xiàn)原生向Flutter傳遞消息。
由于原生向Flutter有可能不止一次消息,這里就需要聲明一個(gè)FlutterEventSink屬性
//單項(xiàng)管道,有可能使用多次
@property (nonatomic, copy) FlutterEventSink eventSink;
然后聲明這個(gè)FlutterEventChannel,
//單項(xiàng)通信管道,原生向Flutter發(fā)送消息
FlutterEventChannel *eventChannel = [FlutterEventChannel eventChannelWithName:@"com.nativeToFlutter" binaryMessenger:flvc];
[eventChannel setStreamHandler:self];
在使用的過程中,需要給setStreamHandler設(shè)置代理,這里將self設(shè)置為FlutterEventChannel的代理。有代理就需要實(shí)現(xiàn)代理方法。
#pragma --mark FlutterStreamHandler代理
- (FlutterError* _Nullable)onListenWithArguments:(id _Nullable)arguments
eventSink:(FlutterEventSink)events {
if (events) {
self.eventSink = events;
self.eventSink(@"從原生傳遞過來(lái)的消息。。。。。。。");
}
return nil;
}
// 不再需要向Flutter傳遞消息
- (FlutterError* _Nullable)onCancelWithArguments:(id _Nullable)arguments {
return nil;
}
在Flutter端也同樣的需要聲明一個(gè)EventChannel,
//注意這里的com.nativeToFlutter一定要與原生的名稱相同,不然沒辦法通信
static const eventChannel = EventChannel('com.nativeToFlutter');
接著在initState方法里面實(shí)現(xiàn)監(jiān)聽:
@override
void initState() {
// TODO: implement initState
super.initState();
//監(jiān)聽接收消息
eventChannel.receiveBroadcastStream().listen(_getData,onError: _getError);
}
//獲得到xiaoxi
void _getData(dynamic data) {
//更新狀態(tài)
setState(() {
_privateString = data.toString();
});
}
//獲取到錯(cuò)誤
void _getError(Object err) {
}
在iOS端的完整代碼如下:
- (IBAction)gotoFlutter:(id)sender {
FlutterViewController *flvc = [[FlutterViewController alloc] init];
//單項(xiàng)通信管道,F(xiàn)lutter向原生發(fā)送消息
FlutterMethodChannel *messageChannel = [FlutterMethodChannel methodChannelWithName:@"com.flutterToNative" binaryMessenger:flvc];
__weak typeof(self) weakSelf = self;
[messageChannel setMethodCallHandler:^(FlutterMethodCall * _Nonnull call, FlutterResult _Nonnull result) {
if ([@"backToNative" isEqualToString:call.method]) {
[weakSelf dismissViewControllerAnimated:true completion:nil];
}
}];
//單項(xiàng)通信管道,原生向Flutter發(fā)送消息
FlutterEventChannel *eventChannel = [FlutterEventChannel eventChannelWithName:@"com.nativeToFlutter" binaryMessenger:flvc];
[eventChannel setStreamHandler:self];
[self presentViewController:flvc animated:true completion:nil];
}
#pragma --mark FlutterStreamHandler代理
- (FlutterError* _Nullable)onListenWithArguments:(id _Nullable)arguments
eventSink:(FlutterEventSink)events {
if (events) {
self.eventSink = events;
self.eventSink(@"從原生傳遞過來(lái)的消息。。。。。。。");
}
return nil;
}
// 不再需要向Flutter傳遞消息
- (FlutterError* _Nullable)onCancelWithArguments:(id _Nullable)arguments {
return nil;
}
運(yùn)行結(jié)果演示如下:
