Flutter混编之打包framework内嵌iOS原生集成

1,938 阅读2分钟

需求

将 Flutter App 模块独立出来,内嵌到 iOS 原生中使用,这里使用的是 framework 方式,优点是多人/多公司/部门开发时,不需要其他人安装 Flutter 环境,只需要引入 iOS Framework 库集成即可。

步骤

依据文档,Flutter 打包 Framework 需为 Flutter Module 类型。

  1. 执行命令 flutter create -t module flutter_module 创建FlutterModule工程

  2. 执行命令 flutter build ios-framework --output=some/path/MyApp/Flutter/ 生成frameworks

    生成的文件结构为:

    some/path/MyApp/
    └── Flutter/
        ├── Debug/
        │   ├── Flutter.xcframework
        │   ├── App.xcframework
        │   ├── FlutterPluginRegistrant.xcframework (only if you have plugins with iOS code)
        │   └── example_plugin.xcframework (each plugin is a separate framework)
        ├── Profile/
        │   ├── Flutter.xcframework
        │   ├── App.xcframework
        │   ├── FlutterPluginRegistrant.xcframework
        │   └── example_plugin.xcframework
        └── Release/
            ├── Flutter.xcframework
            ├── App.xcframework
            ├── FlutterPluginRegistrant.xcframework
            └── example_plugin.xcframework
    

    Flutter.xcframework:Flutter引擎

    App.xcframework:APP代码逻辑

    需要注意,如果工程中含有原生端代码插件,则会生成FlutterPluginRegistrant.xcframeworkxxx_plugin.xcframework,否则则没有。

  3. 在原生iOS端集成

    按照文档初始化Flutter引擎及嵌入Flutter页面(在 iOS 应用中添加 Flutter 页面),需要注意静态库需要将选项设为Do Not Embed

image.png

技巧

  • 如何在已有Flutter APP类型项目中快速打包framework

    一般来说,如果是将已有 Flutter APP 打包为 Framework 的需求,创建拷一份代码给 Flutter Module 类型的话,比较不太好维护。而且 Flutter Module 的文件结构性质(.ios),使项目每次 flutter clean 的时候都会删掉并在 flutter pub get 的时候重新生成,导致我们有些特定配置丢失。

    尝试在Flutter APP类型工程里执行flutter build ios-framework命令,确实也是可以生成frameworks,但是发现当项目中含有插件的时,则会丢失插件的framework。通过比对APP与Module类型的结构,发现APP对比Module有些文件不一致。于是手动在APP工程的ios/Flutter 文件夹下增加 FlutterPluginRegistrant

    image.png

    同时,在项目的Podfile文件中增加

    pod 'FlutterPluginRegistrant', :path => File.join('Flutter', 'FlutterPluginRegistrant'), :inhibit_warnings => true
    

    image.png

    之后执行 flutter build ios-framework命令打包集成测试正常。

  • 原生启动Flutter引擎时如何便捷传值给Flutter层

    参见上篇文章 《Flutter混编之iOS原生传值给Flutter》

  • 打包脚本备忘

    #!/bin/sh
    
    project_path=$(pwd)
    project_last_path=${project_path%/*}
    
    echo ""
    echo "=============== 构建开始 ==============="
    
    clean_tips="执行flutter clean(默认:n) [ y/n ]"
    echo $clean_tips
    read  -t 5 is_clean
    if [  ! -n "${is_clean}" ];then
        is_clean="n"
    fi
    while([[ $is_clean != "y" ]] && [[ $is_clean != "n" ]])
    do
      echo "错误!只能输入[ y/n ] !!!"
      echo $clean_tips
      read is_clean
    done
    
    echo "请输入选择模式(默认:0) [ release: 0 , all: 1 ] "
    read  -t 5 number
    if [  ! -n "${number}" ];then
        number=0
    fi
    while([[ $number != 0 ]] && [[ $number != 1 ]])
    do
      echo "错误!只能输入0或者1!!!"
      echo "请输入选择模式? [ release: 0 , all: 1 ] "
      read number
    done
    
    echo "=============== 复制Podfile配置 ==============="
    cp -fr "$project_path/Podfile" "$project_last_path/Podfile"
    
    
    if [ ${is_clean} = "y" ];then
      echo "=============== 开始清理 ==============="
      flutter clean
    fi
    
    echo "=============== 构建FLUTTER_IOS_FRAMEWORK ==============="
    if [ $number == 0 ];then
      flutter build ios-framework --release --no-debug --no-profile
    else
      flutter build ios-framework
    fi
    
    # TODO 提供选项将新产物复制到旧SDK目录里 仅复制APP/全部复制
    echo "=============== 复制产物 ==============="
    
    echo "=============== 构建完成 ==============="
    echo ""
    exit 0