本文主要从两个点来阐述两者之间的交互:Flutter to OC, OC to Flutter.

Flutter发送消息到OC

有过OC和H5的朋友肯定知道,如果要从H5发送消息到OC,那么需要双方有一个约定的端口来进行识别,Flutter亦然.
这里举一个简单的例子,在Flutter界面点击一个按钮,触发OC的方法,回调一个字符串到Flutter中.
Flutter核心代码如下:

class InteractionState extends State {
 //  对应OC中的FlutterMethodChannel
  static const platform = const MethodChannel('com.allen.test.call');
  String message = 'null message';

  void _getNativeMessage() async{
    String result;
    try {
     // OC回调中对应的”约定” : getFlutterMessage,[1,2,3]:传递参数
      result = await platform.invokeMethod('getFlutterMessage',[1,2,3]);
    } on PlatformException catch (e) {
      result = "error message $e";
    }
    setState(() {
      message = result;
    });
  }
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('test page')
      ),
      body: Center(
        child: Column(
          children: [
            RaisedButton(
              child: Text('get message'),
              onPressed: (){
        // 点击按钮发送消息给OC
                _getNativeMessage();
              },
            ),
        // OC接收到消息之后,会回调一个值过来显示
            Text(message)
          ],
        ),
      ),
    );
  }
}

解释一下上面的代码:

  • MethodChannel: 通过异步的方式和不同平台插件进行通信的命名通道.
  • invokeMethod: 在当前channel执行一个特定的方法,而且可以携带参数.

OC中的代码如下:

- (IBAction)push:(id)sender {
    FlutterViewController *vc = [[FlutterViewController alloc] initWithProject:nil nibName:nil bundle:nil];
    vc.navigationItem.title = @"first flutter app";
    [self.navigationController.navigationBar setHidden:YES];
    [self.navigationController pushViewController:vc animated:YES];
    _vc = vc;
    
    // 从flutter 接收到消息,并传值到OC
   [self getFlutterMessage];
}

- (void)getFlutterMessage{
    FlutterMethodChannel *channel = [FlutterMethodChannel methodChannelWithName:@"com.allen.test.call" binaryMessenger:_vc];
    [channel setMethodCallHandler:^(FlutterMethodCall * _Nonnull call, FlutterResult  _Nonnull result) {
    // Flutter invokeMethod 特定方法的时候会触发到这里
        if ([call.method isEqualToString:@"getFlutterMessage"]) {
            result(@"接收到flutter的消息,回传信息from OC");
            NSLog(@"接收到flutter的参数:%@",call.arguments);
        }
    }];
}
OC发送消息到Flutter

这里实现需求是,native跳转到flutter页面时,传递一个字符串参数过去.

OC发送消息到Flutter的时候,首先需要OC遵守FlutterStreamHandler协议.

FlutterEventChannel *event = [FlutterEventChannel eventChannelWithName:@"com.allen.test.post" binaryMessenger:_vc];
    [event setStreamHandler:self];

实现两个协议方法,在onListenWithArguments方法中回调参数给Flutter,同时Flutter会注册一个监听并传递arguments过来:

- (FlutterError *)onListenWithArguments:(id)arguments eventSink:(FlutterEventSink)events{
    if (events) {
        events(@"OC post message to flutter");
    }
    NSLog(@"arguments 1 : %@",arguments);
    return nil;
}

- (FlutterError *)onCancelWithArguments:(id)arguments{
    NSLog(@"arguments 2 : %@",arguments);
    return nil;
}

在Flutter端,需要注册一个监听,监听com.allen.test.post这个通知.在监听方法中回调OC传递过来的参数.

class InteractionState extends State {
  static const EventChannel eChanel = const EventChannel('com.allen.test.post');
  @override
  void initState(){
    super.initState();
    eChanel.receiveBroadcastStream("flutter 监听了通知").listen(_onEvent,onError: _onError);
  }
  String _message = 'null message';
  //  这里回调过来了参数
  _onEvent(Object event){
    setState(() {
      _message = event.toString();
    });
  }

  _onError(Object error){
    setState(() {
      _message = "error message : $error";
    });
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('test page')
      ),
      body: Center(
    // 这个message就是OC传递过来的值
        child: Text(_message),
      ),
    );
  }
}

以上是两个很简单的例子,解决了基本的交互问题.后续会有更多实用功能的更新.

[Flutter][iOS]Flutter与iOS的交互