iOS工程调用Flutter篇(FlutterBoost框架)

1,477 阅读4分钟

本篇采用Flutter_boost实现分别从原生和Flutter两个维度的代码层面,来介绍内容它们之间的交互方案,

主要有以下步骤:

1.Flutter如何集成Flutter_boost框架

2.iOS如何引入boost的代码实现

3.iOS如何与flutter实现交互

一、Flutter如何集成Flutter_boost框架

1.首先,需要添加FlutterBoost依赖到yaml文件

 flutter_boost:
    git:
      url: 'https://github.com/alibaba/flutter_boost.git'
      ref: '4.2.0'

之后在flutter工程下运行flutter pub get

2.在main.dart文件引入boost,并代码实现集成

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

void main() {
  ///这里的CustomFlutterBinding调用务必不可缺少,用于控制Boost状态的resume和pause
  CustomFlutterBinding();
  runApp(const MyApp());
}

///创建一个自定义的Binding,继承和with的关系如下,里面什么都不用写
class CustomFlutterBinding extends WidgetsFlutterBinding with BoostFlutterBinding {}

3.接入路由跳转

 Map<String, FlutterBoostRouteFactory> routerMap = {
    'indexPage': (settings, uniqueId) {
      return PageRouteBuilder<dynamic>(
          settings: settings,
          pageBuilder: (_, __, ___) => const IndexPager());
    },
    'loginPage': (settings, uniqueId) {
      return PageRouteBuilder<dynamic>(
          settings: settings,
          pageBuilder: (_, __, ___) => LoginPager());
    },
    'withParamPage': (settings, uniqueId) {
      return PageRouteBuilder<dynamic>(
          settings: settings,
          pageBuilder: (_, __, ___) => WithParamPage(uniqueId, settings.arguments as Map<String, dynamic>));
    },
  };

到此dart端就集成完毕了

二、iOS引入Flutter_boost框架

1.首先到自己的iOS目录下,执行pod init,之后执行一次pod install

2.打开创建的Podfile文件,添加以下代码

  flutter_application_path = '../gtech-flutter-sdk'

  load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')
  
  install_all_flutter_pods(flutter_application_path)

添加之后,Podfile应该类似下面这样

flutter_application_path = '../gtech-flutter-sdk'

load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')

target 'flutter_swift' do

  # Comment the next line if you don't want to use dynamic frameworks

  use_frameworks!

  install_all_flutter_pods(flutter_application_path)

end


post_install do |installer|

  flutter_post_install(installer) if defined? (flutter_post_install)

end

然后再执行pod install,安装完成

3.进行准备工作创建FlutterBoostDelegate

import flutter_boost

class BoostDelegate: NSObject,FlutterBoostDelegate {

    

    static let shared = BoostDelegate()

    ///您用来push的导航栏

    var navigationController:UINavigationController?

    

    ///用来存返回flutter侧返回结果的表

    var resultTable:Dictionary<String,([AnyHashable:Any]?)->Void> = [:];

    

    func pushNativeRoute(_ pageName: String!, arguments: [AnyHashable : Any]!) {

        

        print(arguments)

        //可以用参数来控制是push还是pop

        let isPresent = arguments["isPresent"] as? Bool ?? false

        let isAnimated = arguments["isAnimated"] as? Bool ?? true

        //这里根据pageName来判断生成哪个vc,这里给个默认的了

        

        var targetViewController = UIViewController()

        if(pageName == "native_main"){

            let demo = DemoViewController()

            demo.title = "原生测试页"

           

            let data =  arguments?["data"]

            let phone  =  arguments?["mobile"]

            

            let value1 = data!

            let value2 = phone!

            targetViewController = demo

            self.navigationController?.popViewController(animated: true)

            demo .setdata(data: value1 as! String, mobile: value2 as! String)

        }

        

        if(isPresent){

            BoostDelegate.shared.navigationController?.present(targetViewController, animated: isAnimated, completion: nil)

        }else{

            BoostDelegate.shared.navigationController?.pushViewController(targetViewController, animated: isAnimated)

        }

    }

    

    func pushFlutterRoute(_ options: FlutterBoostRouteOptions!) {

        let vc:FBFlutterViewContainer = FBFlutterViewContainer()

        vc.setName(options.pageName, uniqueId: options.uniqueId, params: options.arguments,opaque: options.opaque)

        

        //用参数来控制是push还是pop

        let isPresent = (options.arguments?["isPresent"] as? Bool)  ?? false

        let isAnimated = (options.arguments?["isAnimated"] as? Bool) ?? true

        

        //对这个页面设置结果

        resultTable[options.pageName] = options.onPageFinished;


        //如果是present模式 ,或者要不透明模式,那么就需要以present模式打开页面

        if(isPresent || !options.opaque){

            self.navigationController?.present(vc, animated: isAnimated, completion: nil)

        }else{

            self.navigationController?.pushViewController(vc, animated: isAnimated)

        }

    }

    

    func popRoute(_ options: FlutterBoostRouteOptions!) {

        //如果当前被present的vc是container,那么就执行dismiss逻辑

        if let vc = self.navigationController?.presentedViewController as? FBFlutterViewContainer,vc.uniqueIDString() == options.uniqueId{

            

            //这里分为两种情况,由于UIModalPresentationOverFullScreen下,生命周期显示会有问题

            //所以需要手动调用的场景,从而使下面底部的vc调用viewAppear相关逻辑

            if vc.modalPresentationStyle == .overFullScreen {

                //这里手动beginAppearanceTransition触发页面生命周期

                self.navigationController?.topViewController?.beginAppearanceTransition(true, animated: false)

                vc.dismiss(animated: true) {

                    self.navigationController?.topViewController?.endAppearanceTransition()

                }

            }**else**{

                //正常场景,直接dismiss

                vc.dismiss(animated: **true**, completion: **nil**)

            }

        }else{

            self.navigationController?.popViewController(animated: true)

        }

        //否则直接执行pop逻辑

        //这里在pop的时候将参数带出,并且从结果表中移除

        if let onPageFinshed = resultTable[options.pageName] {

            onPageFinshed(options.arguments)

            resultTable.removeValue(forKey: options.pageName)

        }

    }

}

4.在AppDelegatedidFinishLaunchingWithOptions方法中进行初始化

//创建代理,做初始化操作

        let delegate = BoostDelegate()

        FlutterBoost.instance().setup(application, delegate: delegate) { engine in

        }

到此为止,所有的前置内容均已完成

三、iOS如何与Flutter交互

1.头部引用flutter_boost import flutter_boost

2.原生通过路由跳转到Flutter指定页面

原生代码:

//跳转到首页

    @objc func clickHome(btn:UIButton) {

        let options = FlutterBoostRouteOptions()

        options.pageName = "indexPage"

        BoostDelegate.shared.pushFlutterRoute(options)

    }

Flutter代码:

 'indexPage': (settings, uniqueId) {
      return PageRouteBuilder<dynamic>(
          settings: settings,
          pageBuilder: (_, __, ___) => const IndexPager());
    },

3.通过原生通过路由传参数给Flutter

   原生代码:

//跳转到个人中心

    @objc func clickMine() {

        let options = FlutterBoostRouteOptions()

        options.pageName = "withParamPage"

        options.arguments = ["string": "床前明月光,疑是地上霜","bool":"true","int":"2023"]

        options.uniqueId = "李白"

        options.completion = { completion **in**

           print("open operation is completed")

        }

        BoostDelegate.shared.pushFlutterRoute(options)

    }

Flutter代码:

'withParamPage': (settings, uniqueId) {
      return PageRouteBuilder<dynamic>(
          settings: settings,
          pageBuilder: (_, __, ___) => WithParamPage(uniqueId, settings.arguments as Map<String, dynamic>));
    },

4.Flutter打开原生路由

   原生代码:

if(pageName == "native_main"){

            let demo = DemoViewController()

            demo.title = "原生测试页"

            targetViewController = demo

            self.navigationController?.popViewController(animated: true)

        }

Flutter代码:

BoostNavigator.instance.push("native_main", arguments: {'data': "我是flutter传过来的参数",'mobile': "15821963583"});

5.接受来自Flutter的事件&数据

  原生代码:

//这里注册事件监听,监听flutter发送到iOS的事件

        self.backListener =  FlutterBoost.instance().addEventListener({[weak self] key, dic in

            //在这里处理你的事件

            print(dic ?? "")

            print("接受到来自 flutter的事件 ");

            let back = dic?["com"] as! String

            lbl1.text = "flutter 返回 " + back

            self?.navigationController?.popViewController(animated: true)

        }, forName: "eventToNative")

Flutter代码:

BoostChannel.instance.sendEventToNative("eventToNative",{"android":"mmj","com":"shanghai"});

四、各版本包大小对比

iOS空包:31k

Flutter集成boost包:7.6M

iOS集成Flutter后的包: 7.7M

image.png