当前位置:   article > 正文

Flutter 知识 (Swift) flutter跨平台通讯 flutter与iOS通讯 flutter与安卓(Android)通讯 通道_flutter 和ios 消息传递

flutter 和ios 消息传递

一直觉得自己写的不是技术,而是情怀,一个个的教程是自己这一路走来的痕迹。靠专业技能的成功是最具可复制性的,希望我的这条路能让你们少走弯路,希望我能帮你们抹去知识的蒙尘,希望我能帮你们理清知识的脉络,希望未来技术之巅上有你们也有我。

在这里插入图片描述
通讯-FLutter跟iOS通讯所有代码例子

无参数,无返回值,Flutter Call iOS

Flutter
直接说一下flutter的核心代码.

创建对象

// 创建与iOS沟通的渠道
// 该方法用于flutter主动发消息给iOS监听的
var channel = const MethodChannel('com.pages.flutter');
  • 1
  • 2
  • 3

iOS

channel.invokeMethod('red_view_controller', null);
  • 1

iOS
iOS这边的核心代码
在这里插入图片描述

let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
MethodChannelDemo(messenger: controller.binaryMessenger)
  • 1
  • 2

在这里插入图片描述

import Flutter
import UIKit

public class MethodChannelDemo {
    
    var count =  0
    var channel:FlutterMethodChannel
    
    init(messenger: FlutterBinaryMessenger) {
        //与flutter建立通道     "com.pages.flutter"的通道命名要与flutter一致
        channel = FlutterMethodChannel(name: "com.pages.flutter", binaryMessenger: messenger)
        //接收来自flutter传过来的值。    'sendData'的方法命名与flutter要一致
        channel.setMethodCallHandler { (call:FlutterMethodCall, result:@escaping FlutterResult) in
            if (call.method == "red_view_controller") {//唤起自定义原生控制器
                let viewController = RedViewController()
                if let rootViewController = UIApplication.shared.keyWindow?.rootViewController {
                    rootViewController.present(viewController, animated: true, completion: nil)
                }
            }
        }

    }
    

}
  • 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

RedViewController就不写了,里面两个Label用于显示的

有参数,无返回值,Flutter Call iOS

Flutter

// 创建与iOS沟通的渠道
// 该方法用于flutter主动发消息给iOS监听的
var channel = const MethodChannel('com.pages.flutter');
  • 1
  • 2
  • 3
channel.invokeMethod('red_view_controller', {'name': 'laomeng', 'age': '18'});
  • 1

iOS

在这里插入图片描述

let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
MethodChannelDemo(messenger: controller.binaryMessenger)
  • 1
  • 2

在这里插入图片描述

import Flutter
import UIKit

public class MethodChannelDemo {
    
    var count =  0
    var channel:FlutterMethodChannel
    
    init(messenger: FlutterBinaryMessenger) {
        //与flutter建立通道     "com.pages.flutter"的通道命名要与flutter一致
        channel = FlutterMethodChannel(name: "com.pages.flutter", binaryMessenger: messenger)
        //接收来自flutter传过来的值。    'sendData'的方法命名与flutter要一致
        channel.setMethodCallHandler { (call:FlutterMethodCall, result:@escaping FlutterResult) in
            if (call.method == "red_view_controller") {//唤起自定义原生控制器
                var nameParams = String()
                var ageParams = String()
                if let dict = call.arguments as? Dictionary<String, Any> {//把接收到的值转换成字典
                    nameParams = dict["name"] as? String ?? "" //通过字典的key获取对应的value
                    ageParams = dict["age"] as? String ?? "" //通过字典的key获取对应的value
                }
                
                let viewController = RedViewController()
                viewController.name = nameParams
                viewController.age = ageParams
                if let rootViewController = UIApplication.shared.keyWindow?.rootViewController {
                    rootViewController.present(viewController, animated: true, completion: nil)
                }
            }
        }

    }
   
}
  • 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

RedViewController就不写了,里面两个Label用于显示的

有参数,有返回值,Flutter Call iOS

Flutter

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class Category extends StatefulWidget {
  const Category({Key? key}) : super(key: key);

  @override
  State<Category> createState() => _Category();
}

class _Category extends State<Category> {

  // 创建与iOS沟通的渠道
  // 该方法用于flutter主动发消息给iOS监听的
  var channel = const MethodChannel('com.pages.flutter');

  //  原生回调的数据
  var _callbackData;

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            TextButton(
              child: const Text('调起原生的控制器,有参数,无返回值'),
              onPressed: () async {
                var result = await channel.invokeMethod('red_view_controller', {'name': 'laomeng', 'age': '18'});
                var name = result['name'];
                var age = result['age'];
                setState(() {
                  print('返回的名称: $name result $result');
                  _callbackData = 'name: $name age: $age';
                });
              },
            ),
            Text('原生收到相应并返回数据:$_callbackData'),
          ],
        ),
      ),
    );
  }

}
  • 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

iOS

在这里插入图片描述

let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
MethodChannelDemo(messenger: controller.binaryMessenger)
  • 1
  • 2

在这里插入图片描述

import Flutter
import UIKit

public class MethodChannelDemo {
    
    var count =  0
    var channel:FlutterMethodChannel
    
    init(messenger: FlutterBinaryMessenger) {
        //与flutter建立通道     "com.pages.flutter"的通道命名要与flutter一致
        channel = FlutterMethodChannel(name: "com.pages.flutter", binaryMessenger: messenger)
        //接收来自flutter传过来的值。    'sendData'的方法命名与flutter要一致
        channel.setMethodCallHandler { (call:FlutterMethodCall, result:@escaping FlutterResult) in
            if (call.method == "red_view_controller") {//唤起自定义原生控制器
                var nameParams = String()
                var ageParams = String()
                if let dict = call.arguments as? Dictionary<String, Any> {//把接收到的值转换成字典
                    nameParams = dict["name"] as? String ?? "" //通过字典的key获取对应的value
                    ageParams = dict["age"] as? String ?? "" //通过字典的key获取对应的value
                    result(["name":"return \(nameParams)","age":"return \(ageParams)"])
                }
                let viewController = RedViewController()
                viewController.name = nameParams
                viewController.age = ageParams
                if let rootViewController = UIApplication.shared.keyWindow?.rootViewController {
                    rootViewController.present(viewController, animated: true, completion: nil)
                }
            }
        }

    }
    

}
  • 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

RedViewController就不写了,里面两个Label用于显示的

有参数,无返回值,iOS Call Flutter

iOS
在这里插入图片描述

let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
let _ = MethodChannelDemo(messenger: controller.binaryMessenger)
  • 1
  • 2

在这里插入图片描述

import Flutter
import UIKit

public class MethodChannelDemo {
    
    var channel:FlutterMethodChannel
    
    init(messenger: FlutterBinaryMessenger) {
        //与flutter建立通道     "com.flutter.guide.MethodChannel"的通道命名要与flutter一致
        channel = FlutterMethodChannel(name: "com.flutter.guide.MethodChannel", binaryMessenger: messenger)
        //接收来自flutter传过来的值。    'sendData'的方法命名与flutter要一致
        channel.setMethodCallHandler { (call:FlutterMethodCall, result:@escaping FlutterResult) in//flutter call ios
            if (call.method == "dumpViewController") {
                let viewController = ViewController()
                if let rootViewController = UIApplication.shared.keyWindow?.rootViewController {
                    rootViewController.present(viewController, animated: true, completion: nil)
                }
            }
        }
    }
    
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

iOS(Swift)控制器调用flutter的核心代码

import UIKit
import Flutter

class ViewController: UIViewController {
    

    lazy private var btnOne: UIButton = {
        let button = UIButton()
        button.backgroundColor = .blue
        button.addTarget(self, action: #selector(buttonOneClick), for: .touchUpInside)
        return button
    }()
    
    lazy private var btnTwo: UIButton = {
        let button = UIButton()
        button.backgroundColor = .blue
        button.addTarget(self, action: #selector(buttonTwoClick), for: .touchUpInside)
        return button
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        
        view.addSubview(btnOne)
        view.addSubview(btnTwo)
    }
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        
        btnOne.frame = CGRectMake(view.bounds.size.width*0.5 - 25, view.bounds.size.height*0.5 - 100, 50, 50)
        btnTwo.frame = CGRectMake(view.bounds.size.width*0.5 - 25, view.bounds.size.height*0.5 + 100, 50, 50)
    }
    
    //ios call flutter, call success not return value
    @objc func buttonOneClick() {
        guard let controller = UIApplication.shared.keyWindow?.rootViewController as? FlutterViewController else {
            return
        }
        let channel = FlutterMethodChannel(name: "com.flutter.guide.MethodChannel", binaryMessenger: controller.binaryMessenger)
        let args = ["name":"方法1"]
        channel.invokeMethod("funcOne", arguments:args)
        
        dismiss(animated: true)
    }
    
    //ios call flutter, call success return value
    @objc func buttonTwoClick() {
        guard let controller = UIApplication.shared.keyWindow?.rootViewController as? FlutterViewController else {
            return
        }
        let channel = FlutterMethodChannel(name: "com.flutter.guide.MethodChannel", binaryMessenger: controller.binaryMessenger)
        let args = ["name":"方法2"]
        channel.invokeMethod("funcTwo", arguments:args) { (result) in
            if let resultString = result as? String {
                print("ios: \(resultString)")
            }
        }
        
        dismiss(animated: true)
    }


}
  • 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

Flutter
核心代码

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();

}

class _MyHomePageState extends State<MyHomePage> {

  // 创建与iOS沟通的渠道
  var channel = const MethodChannel('com.flutter.guide.MethodChannel');

  //  原生返回给我们的数据
  var _nativeData;

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

    channel.setMethodCallHandler(_handleMethod);

    //该方法用于接收ios传过来的值(该方法时时刻刻的在监听获取iOS传递过来的值)
    channel.setMethodCallHandler((call) {
      setState(() {
        _nativeData = call.arguments['name'];
      });
      // 返回一个非空的Future<void>
      //return Future<void>.value();//回调空值
      return Future.value('flutter接收到ios的值之后,回调当前字符串给iOS');
    });

  }

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            TextButton(
              child: const Text('弹出控制器'),
              onPressed: () async {
                channel.invokeMethod('dumpViewController', null);
              },
            ),
            Text('原生主动发送数据给Flutter接收:$_nativeData')
          ],
        ),
      ),
    );
  }

  Future<dynamic> _handleMethod(MethodCall call) async {
    switch (call.method) {
      case 'funcOne':
        setState(() {
          _nativeData = call.arguments['name'];
        });
        return Future<void>.value();//回调空值
        //break;
      case 'funcTwo':
        setState(() {
          _nativeData = call.arguments['name'];
        });
        // 返回一个非空的Future<void>
        return Future.value('flutter接收到ios的值之后,回调当前字符串给iOS');
        //break;
        // 添加其他方法的处理逻辑
      default:
        throw MissingPluginException();
    }
  }

}
  • 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

有参数,有返回值,iOS Call Flutter

下面的方法是使用监听的方法,iOS那边的代码是没有问题的,但是flutter那边稍微是有点问题,iOS调用flutter已经把值传递过去了,已经打印出来收到了,但是调用setState没有更新UI,不知道什么原因

Flutter

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class Category extends StatefulWidget {
  const Category({Key? key}) : super(key: key);

  @override
  State<Category> createState() => _Category();
}

class _Category extends State<Category> {

  // 创建与iOS沟通的渠道
  // 该方法用于flutter主动发消息给iOS监听的
  var channel = const MethodChannel('com.pages.flutter');

  //flutter 接收swift 信息的通道(实时监听)
  //该方法用于 iOS主动发信息给flutter进行监听的
  static const EventChannel eventChannel = EventChannel('com.pages.flutter');//App/Event/Channel和iOS的一致

  //  ios主动发消息给flutter接收的值
  var _nativeData;

  // 错误处理
  void _onError(dynamic) {}

  // 数据接收
  void _onEvent(dynamic value) {
    print('iOS data + $value');
    setState(() {
      // _nativeData = value.toString();
      // print('setState + $_nativeData');
      _nativeData = value["hello123"];
      print('setState + $_nativeData');
    });
  }

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

    //开始监听,swfit 发来的的消息
    eventChannel.receiveBroadcastStream("init").listen((dynamic value){
      setState(() {
        _nativeData = value["hello123"];
        print('setState + $_nativeData');
      });
    }, onError: _onError);

  }

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            TextButton(
              child: const Text('11111'),
              onPressed: () async {

              },
            ),
            TextButton(
              child: const Text('调起原生的控制器:view_controller'),
              onPressed: () async {
                channel.invokeMethod('run_viewController', null);
              },
            ),
            // Text('原生返回数据:$_callbackData'),
            // Text('原生返回数据:$_data'),
            Builder(
              builder: (BuildContext context) {
                if (_nativeData != null) {
                  return Text('原生主动发送数据给Flutter接收:$_nativeData');
                } else {
                  return Text('等待数据...');
                }
              },
            ),
          ],
        ),
      ),
    );
  }

}

  • 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
  • 91

iOS
控制器的核心代码

import UIKit
import Flutter

class ViewController: UIViewController, FlutterStreamHandler {
    
    var channel:FlutterEventChannel?//频道通道
    var eventSink:FlutterEventSink?//事件通道(用于将事件发送给Flutter)
    var flutterViewController:FlutterViewController? = nil//用于在iOS应用程序中显示Flutter内容。
    //创建了一个延迟加载的FlutterEngine实例,名称为"my flutter engine",FlutterEngine负责运行一个Flutter应用程序
    lazy var flutterEngine:FlutterEngine = FlutterEngine(name: "my flutter engine")

    lazy private var button: UIButton = {
        let button = UIButton()
        button.backgroundColor = .blue
        button.addTarget(self, action: #selector(buttonClick), for: .touchUpInside)
        return button
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        
        view.addSubview(button)

        // 初始化Flutter引擎(启动flutter程序)
        flutterEngine.run()
        flutterViewController = FlutterViewController(engine: flutterEngine, nibName: nil, bundle: nil)
        //初始化事件通道
        channel = FlutterEventChannel(name: "com.pages.flutter", binaryMessenger: flutterViewController as! FlutterBinaryMessenger)
        channel?.setStreamHandler(self)

    }
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        
        button.frame = CGRectMake(view.bounds.size.width*0.5 - 25, view.bounds.size.height*0.5 - 25, 50, 50)
    }
    
    @objc func buttonClick() {
        //获取flutter那边的通道
        let  method = FlutterMethodChannel(name: "com.pages.flutter", binaryMessenger: flutterViewController as! FlutterBinaryMessenger)
        method.setMethodCallHandler { (callBack:FlutterMethodCall,  result:FlutterResult) -> Void in
        //获取flutter 返回的信息
            print(callBack.method,callBack.arguments ?? "")
            if callBack.method == "method_native_result_callback" {//调用方法
                // 向Flutter发送响应消息
                result("flutter: hello")//回调信息过去
            }
        }

        //swift 主动发送信息给flutter
        let dic:[String:String] = ["hello123":"flutter456"];
        self.eventSink?(dic)

        //这里如果创建一个新的flutter页面出来,返回的值显示上有更新,不过UI界面有问题
//        self.present(flutterViewController!, animated: true, completion: nil)
        //这里返回有结果收到了,但是UI显示label没有更新显示,UI界面没有问题
        dismiss(animated: true)
    }

    // MARK: - FlutterStreamHandler 协议方法
    //ios 主动给flutter 发送消息回调方法
    //当Flutter客户端开始监听事件时,onListen方法会被调用,它提供了一个事件sink,用于向Flutter客户端发送事件
    func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {
        self.eventSink = events
        return nil
    }
    
    //FlutterStreamHandler协议所必需的
    //Flutter客户端停止监听事件时被调用
    func onCancel(withArguments arguments: Any?) -> FlutterError? {
        return nil
    }

}

  • 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

在这里插入图片描述

let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
let _ = MethodChannelDemo(messenger: controller.binaryMessenger)
  • 1
  • 2

在这里插入图片描述

import Flutter
import UIKit

public class MethodChannelDemo {
    
    var channel:FlutterMethodChannel
    
    init(messenger: FlutterBinaryMessenger) {
        //与flutter建立通道     "com.flutter.guide.MethodChannel"的通道命名要与flutter一致
        channel = FlutterMethodChannel(name: "com.flutter.guide.MethodChannel", binaryMessenger: messenger)
        //接收来自flutter传过来的值。    'sendData'的方法命名与flutter要一致
        channel.setMethodCallHandler { (call:FlutterMethodCall, result:@escaping FlutterResult) in//flutter call ios
            if (call.method == "dumpViewController") {
                let viewController = ViewController()
                if let rootViewController = UIApplication.shared.keyWindow?.rootViewController {
                    rootViewController.present(viewController, animated: true, completion: nil)
                }
            }
        }
    }
    
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/383264
推荐阅读
相关标签
  

闽ICP备14008679号