iOS與Flutter相互通信

iOS與Flutter相互通信

iOS項(xiàng)目加入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)行演示:


goto_flutter.gif

到此最簡(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)行代碼演示:


flutter_to_native.gif

原生發(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é)果演示如下:


native_to_flutter.gif
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 運(yùn)行一個(gè)原生的Flutter工程(也就是純Flutter)非常簡(jiǎn)便,不過現(xiàn)在Flutter屬于試水階段,要是想在商...
    Realank閱讀 9,543評(píng)論 10 32
  • 我買了一張票 在暮色蒼茫中 坐上了開往春天的列車 古老的車廂里 燈火輝煌眩目,而窗外 無(wú)邊的夜色已悄然降臨 我的鄰...
    文佑閱讀 455評(píng)論 0 6
  • 2017-01-14原文:當(dāng)我們長(zhǎng)大后,離開他們,只有當(dāng)我們有求于他們或遇到麻煩的時(shí)候,我們才回家。你可能覺得男孩...
    請(qǐng)叫我四爺閱讀 1,251評(píng)論 0 2
  • 處暑之時(shí)憂中暑,熬完夏日秋如虎。 何時(shí)真正有涼風(fēng)?吹盡人間炎熱苦。
    梅園詩(shī)隱閱讀 894評(píng)論 3 14
  • 美好的一天從早起開始,美好的一天從早睡結(jié)束。美好的、有儀式感的、和戰(zhàn)友們一起早起的一天又開始了,今天早起打卡的一句...
    幸福就是剛剛好閱讀 325評(píng)論 0 0

友情鏈接更多精彩內(nèi)容