iOS 工程集成 flutter module

101 阅读4分钟

前言:

在原有的iOS工程中,集成flutter module也是一种常见的开发模式。可以保证之前业务的稳定性,新的模块完全可以使用flutter来实现。当然中间也会涉及到很多的问题,比如 引入flutter 方式,多引擎还是单引擎,iOS和flutter怎么交互等等。

一、引入方式

第一种方案: Flutter 官方已经给出的混编方案:

github.com/flutter/flu…

文档里写的比较清楚了的,这里就不再多做赘述,大意就是说现在我们只需要在iOS工程的podfile文件中添加如下命令。

# Uncomment the next line to define a global platform for your project
flutter_application_path = '../flutter'
load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')

platform :ios, '13.0'

target 'Project' do
  # Comment the next line if you don't want to use dynamic frameworks
  # use_frameworks!

  # Pods for Project

  install_all_flutter_pods(flutter_application_path)

  pod 'AFNetworking', '~> 4.0.1'
  pod 'SDWebImage','~> 5.19.7'
  pod 'Masonry', '~> 1.1.0',:inhibit_warnings => true
  pod 'YYModel'
  pod 'YYCategories', '~> 1.0.4'
  pod 'MJRefresh', '~> 3.5.0'
  pod 'SVProgressHUD'
  pod 'SDCycleScrollView'

  target 'ProjectTests' do
    inherit! :search_paths
    # Pods for testing
  end

  target 'ProjectUITests' do
    # Pods for testing
  end

  post_install do |installer|
      installer.pods_project.targets.each do |target|
        target.build_configurations.each do |config|
          config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.0'
        end
      end
      flutter_post_install(installer)
    end
end

然后执行 pod install 即可,这种引入方式要求每个开发的人都需要在本地电脑配置好 flutter 环境,不然是跑不起来的。这种方式相对来说对于不需要关注 flutter 模块的开发者是很头疼的,比如第一次需要打开 flutter 代码,选择依赖的 flutterSDK,然后执行 flutter pub get ,然后在进入 iOS 目录下,执行 pod install。在比如flutter模块引入新的插件了,还得按照以上流程来一遍,很麻烦。

第二种方案: iOS集成flutter的编译产物

flutterframework 的形式通过 Cocoapods 引入 iOS 工程,iOS 只需要关注 flutter 的编译产物,不需要配置本地环境,不需要关注 flutter 代码的变化。Podfile文件如下所示,flutter 更新完后只需要执行下 pod install 即可,对象原生项目0侵入。

# Uncomment the next line to define a global platform for your project

platform :ios, '13.0'

target 'Project' do

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

  use_frameworks!

  # Pods for Project

  pod 'FlutterPod',:git=>'https://gitee.com/TTGF/flutter_pod.git'

  pod 'AFNetworking', '~> 4.0.1'

  pod 'SDWebImage','~> 5.19.7'

  pod 'Masonry', '~> 1.1.0',:inhibit_warnings => true

  pod 'YYModel'

  pod 'YYCategories', '~> 1.0.4'

  pod 'MJRefresh', '~> 3.5.0'

  pod 'SVProgressHUD'

  pod 'SDCycleScrollView'

  target 'ProjectTests' do

    inherit! :search_paths

    # Pods for testing

  end

  target 'ProjectUITests' do

    # Pods for testing
  end

  post_install do |installer|

      installer.pods_project.targets.each do |target|

        target.build_configurations.each do |config|

          config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.0'

        end

      end

    end

end
1. 创建 iOS 工程

自行创建即可

2. 创建名字为‘ FlutterPod’的Pod库
$ cd ~/Desktop/(文件夹)
$ pod lib create FlutterPod

终端依次输入所需类型:

xingkunkun:FlutterForFW admin$ pod lib create MyFlutterPod
Cloning `https://github.com/CocoaPods/pod-template.git` into `MyFlutterPod`.
Configuring MyFlutterPod template.
------------------------------
To get you started we need to ask a few questions, this should only take a minute.

What platform do you want to use?? [ iOS / macOS ]
 > ios
What language do you want to use?? [ Swift / ObjC ]
 > objc
Would you like to include a demo application with your library? [ Yes / No ]
 > no
Which testing frameworks will you use? [ Specta / Kiwi / None ]
 > none
Would you like to do view based testing? [ Yes / No ]
 > no
What is your class prefix?
 > Kevin

Running pod install on your new library.

创建完了之后如下图所示:

WX20250909-120216@2x.png

3. 在FlutterPod目录下创建 Flutter Module模块

创建完后如下图所示

WX20250909-133545@2x.png

4. 在 pubspec.yaml 文件中加入插件

pubspec.yaml 文件中加入开发所需的插件,以下是我的 pubspec.yaml 文件。

name: flutter_novel
description: "A new Flutter project."

version: 1.0.0+1

environment:
  sdk: ^3.8.0

dependencies:
  flutter:
    sdk: flutter

  cupertino_icons: ^1.0.8
  flutter_screenutil: ^5.9.3
  pull_to_refresh: ^2.0.0
  logger: ^1.3.0
  dio: ^5.8.0+1
  fluro: ^2.0.5
  fluttertoast: ^8.2.12
  flutter_easyloading: ^3.0.5
  flutter_bloc: ^8.1.2
  extended_image: ^10.0.1
  status_bar_control:
    git:
      url: https://gitee.com/TTGF/status_bar_control.git
  flutter_localizations:
    sdk: flutter

dev_dependencies:
  flutter_test:
    sdk: flutter
  flutter_lints: ^5.0.0

flutter:
  uses-material-design: true
  assets:
    - assets/images/
    - mock/
  module:
    androidX: true
    androidPackage: com.example.flutter_novel
    iosBundleIdentifier: com.example.flutterNovel
5. 编译

执行以下任意一个命令

$ flutter build ios --debug      
或者
$ flutter build ios --release --no-codesign 

会发现flutter_module 会生成一个build文件夹,里面装的就是需要的编译产物,如下图所示。

WX20250909-134613@2x.png

需要 debug 版本的执行 flutter build ios --debug 对应的文件夹就是 Debug-iphoneos

需要 release 版本的执行 flutter build ios --release 对应的文件夹就是 Release-iphoneos

然后将这些 framework 放在 flutter_pod 的一个文件夹里面上传 git

为了提高开发效率使用可以以下脚本,(自己手动操作也是没有问题的)。

flutter_module 模块下下创建脚本文件

$ cd ../flutter_module
$ touch compile_project.sh   // 创建脚本
$ open compile_project.sh   

将下面代码复制进 compile_project.sh

if [ -z $out ]; then
    out='ios_frameworks'
fi

echo "准备输出所有文件到目录: $out"

echo "清除所有已编译文件"
find . -d -name build | xargs rm -rf
flutter clean
rm -rf $out
rm -rf build
source ~/.bash_profile
flutter clean
flutter pub get

addFlag(){
    cat .ios/Podfile > tmp1.txt
    echo "use_frameworks!" >> tmp2.txt
    cat tmp1.txt >> tmp2.txt
    cat tmp2.txt > .ios/Podfile
    rm tmp1.txt tmp2.txt
}

echo "检查 .ios/Podfile文件状态"
a=$(cat .ios/Podfile)
if [[ $a == use* ]]; then
    echo '已经添加use_frameworks, 不再添加'
else
    echo '未添加use_frameworks,准备添加'
    addFlag
    echo "添加use_frameworks 完成"
fi

echo "编译flutter"
flutter build ios --debug
#release下放开下一行注释,注释掉上一行代码
#flutter build ios --release --no-codesign
echo "编译flutter完成"
mkdir $out
cp -r build/ios/Debug-iphoneos/*/*.framework $out
#release下放开下一行注释,注释掉上一行代码
#cp -r build/ios/Release-iphoneos/*/*.framework $out

cp -r build/ios/Debug-iphoneos/App.framework $out
cp -r build/ios/Debug-iphoneos/Flutter.framework $out

#cp -r build/ios/Release-iphoneos/App.framework $out
#cp -r build/ios/Release-iphoneos/Flutter.framework $out

echo "复制framework库到临时文件夹: $out"

libpath='../'

rm -rf "$libpath/ios_frameworks"
mkdir $libpath
cp -r $out $libpath

echo "复制库文件到: $libpath"

然后在终端执行脚本文件

$ sh compile_project.sh   

就会将编译所生成的 frameworks 放在 ios_frameworks 文件夹里面。

WX20250909-140210@2x.png

6. 上传 git
6.1 创建仓库,建立链接。

自己操作就行了。

6.2 修改 flutter_pod .gitignore 文件,注意 这是个隐藏文件。只需要上传编译产物即可,不需要上传 flutter_module 源代码。

代码如下:

# macOS
.DS_Store

# Xcode
build/
DerivedData/
*.xcworkspace/  # 注意:不要忽略整个 .xcworkspace,只忽略内部生成内容
xcuserdata/

# Carthage
Carthage/Build

# 暂时保留 Pods/ 目录的忽略,根据团队规范决定
# Pods/
#ignore flutter_module 工程文件
flutter_module/
EOF
6.3 修改 FlutterPod.podspec 文件

代码如下:


Pod::Spec.new do |s|

  s.name             = 'FlutterPod'

  s.version          = '0.1.0'

  s.summary          = 'A short description of FlutterPod.'

  s.description      = <<-DESC

TODO: Add long description of the pod here.

                       DESC
                       
  s.homepage         = 'https://gitee.com/TTGF/flutter_pod.git'

  s.license          = { :type => 'MIT', :file => 'LICENSE' }

  s.author           = { 'litingting' => '13161138626@163.com' }

  s.source           = { :git => 'https://gitee.com/TTGF/flutter_pod.git', :tag => s.version.to_s}

  s.ios.deployment_target = '10.0'

  s.static_framework = true

  p = Dir::open ("ios_frameworks")

  arr = Array.new

  arr.push('ios_frameworks/*.framework')

  s.ios.vendored_frameworks = arr

end

不然会出现识别不到 frameworks 的问题。

6.4 上传

上传就完了,无论是使用命令或者可视化软件都行。

6.5 引入使用

在Podfile 文件中 增加

pod 'FlutterPod',:git=>'https://gitee.com/TTGF/flutter_pod.git'

执行 pod install 打开 iOS 项目 如下图所示

WX20250909-142249.png

就说明成功了,已经将编译产物引入 iOS 工程了。

这样原生开发人员,不需要配置 flutter 开发环境,再也不需要关注是否需要执行 pub get 了,不需要关注flutter 模块报错等各种问题了,每次只需要执行 pod install 即可。

二、原生代码开发

// 当使用共享引擎时,Flutter 引擎会保持之前页面的状态 initState 方法只走了一次

// 单引擎方案

// 多引擎方案

// 单引擎缓存问题

// 首次白屏问题解决(loading问题)

// 方法通信问题

// AppDelegate 中初始化的 FlutterEngine 确实会对自定义导航栏位置产生影响 (延时初始化,等到第一次使用时初始化)

// 路由方案

// 文件识别不到 因为 .gitignore 文件原因

未完待续。。。。。。