40

Flutter - 将 Flutter 集成到现有项目(iOS - Framework篇)

 3 years ago
source link: http://mp.weixin.qq.com/s?__biz=MzU4NzkzMDkxMw%3D%3D&%3Bmid=2247483977&%3Bidx=1&%3Bsn=3a286e7fec8eb5cb5746bc3df55598b9
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

本篇文章大幅参考了 caijinglong 大佬的总结文章: 把flutter作为framework添加到已存在的iOS中 [1]

用 Flutter 来开发,从来都不可能是新开的一个纯 Flutter 项目,很大一部分都是 老项目接入 Flutter 来混编。

Flutter 官网 - Adding to an iOS app [2] 这里,官方也给出了一些将 Flutter 集成进入现有 iOS 项目的方法。但是,这些都多多少少的不符合我们的需求。

1. 从 Flutter Module 说起

想要把 Flutter 集成进现有 iOS 项目,我们就必须使用 Flutter Module

那就先用命令创建一个 Flutter Module: flutter create --template module flutter_test_module

nE3Avqr.jpg!web

Flutter APP 和 Flutter Module 的不同之处在于 pubspec.yaml 最后一段:

# This section identifies your Flutter project as a module meant for

# embedding in a native host app. These identifiers should _not_ ordinarily

# be changed after generation - they are used to ensure that the tooling can

# maintain consistency when adding or modifying assets and plugins.

# They also do not have any bearing on your native host application's

# identifiers, which may be completely independent or the same as these.

module:

androidX: true

androidPackage: com.example.flutter_test_module

iosBundleIdentifier: com.example.flutterTestModule

这一段代码,把该 Flutter 项目标注为一个 module,用于嵌入到原生 app 里。

这里面设置了是否使用 androidx,Android 和 iOS 的 APP id。

2. iOS原生项目所需的文件

先说一下,iOS 原生项目引入 Flutter Module 需要如下 Framework:

1. Flutter.framework 2. App.framework 3. FlutterPluginRegistrant.framework (如果有用到原生的插件 - 非纯 dart 编写) 4. Pods_Runner.framework(如果有用到原生的插件 - 非纯 dart 编写) 5. *.framework(插件的 framework)

下面继续集成。

Flutter Module 创建完成后,先来给 iOS 打个包,命令如下: flutter build ios --release --no-codesign

然后看一下打包出来的东西,路径为 build->ios->Release-iphoneos

v6vYVnR.jpg!web

如果有第三方库的话,这里面应该是有上面说的 3、4、5 的 framework,但是我们刚创建项目,什么都没有加,所以是没有任何 framework的。

然后去 .ios/Flutter 里找 1、2:

I7zymiZ.jpg!web

但是我们写程序不可能什么插件都不用,所以加上一个 shared_preferences [3] ,再来打包看一下 build 文件夹:

u2eqyq6.jpg!web

可以看到确实出现了我们上面说的 3、4、5 framework,这样我们所需的 framework 全部集齐。

3. 使用 cocoapods + git 来管理

因为 caijinglong 大佬 文章内说:

因为找遍了 podfile 的相关文档, 没有找到可以直接引用 framework 的方式

所以需要一个 pod 库作为"中转”

所以我们就要 跟着做!

2qUJFbj.jpg!web

使用命令 pod lib create flutter-lib 来创建一个 名为 flutter-lib的私有库。

创建完成之后,打开 flutter-lib.podspec ,在  end 前面加入一行:

7ju6jaZ.jpg!web

接着我们在该文件夹内创建一个名为 ios_frameworks 的文件夹,把我们刚才的那么多 framework 全都粘贴过来。

viQVb2V.jpg!web

这个时候我们的iOS原生项目就可以引入本地这个库了:

platform :ios, '8.0'

use_frameworks!


target 'xxx.xxx.xxx' do

pod 'flutter-lib', :path => 'somepath/flutter-lib'

end

当然,我们不可能都用本地路径来引入,所以我们把这整个 flutter-lib 文件夹传到 git 上,然后这样引用:

platform :ios, '8.0'

use_frameworks!


target 'xxx.xxx.xxx' do

pod 'flutter-lib', :git => 'http://xxxx.git'

end

这样我们就可以从 git 上来远程引用该私有库了。

如果运行有错误的话,可以去 caijinglong 大佬的博客查看解决办法。 [4]

4. 编写脚本自动处理

上面都是手动来处理的,包括打包->移动文件->上传git等。

下面就写一个脚本来处理一下(基于 caijinglong 大佬):

ios_project_name='xxx' # 项目名称

ios_out_path='xxx/ios_frameworks' # 文件输出路径

flutter_git_path='http://xxx/xxx/xxx.git' # git 项目路径


function customEcho(){

echo "\033[1;32m$1\033[0m"

}

customEcho '\n1. 执行 flutter clean'

flutter clean || exit -1


customEcho '\n2. 清空build文件夹'

rm -rf $ios_project_name

rm -rf build

echo '清空完成'


customEcho '\n3. 生成 iOS frameworks'

flutter build ios --release --no-codesign || exit -1


customEcho "\n4. 从 git 上克隆 frameworks 项目"

git clone $flutter_git_path || exit -1


customEcho "\n5. 输出文件到 $ios_out_path"

rm -rf $ios_out_path

mkdir $ios_out_path



cp -r build/ios/Release-iphoneos/*/*.framework $ios_out_path

cp -r .ios/Flutter/App.framework $ios_out_path

# cp -r .ios/Flutter/engine/Flutter.framework $out

echo '输出完成'


customEcho "\n6. 提交文件到 git"

cd $ios_project_name

git add .

git commit -m 'update lib'

git push -u origin master



customEcho "\n7. 删除该文件夹"

cd ..

rm -rf $ios_project_name


customEcho "\nAll Done."

解释就不用解释了,上面的输出都有写。

这里有一点,就是 Flutter.framework 超级大 ,有四五百兆,我们把它单独放在了一个 pod 里,而剩下的一些每次新增插件或变更代码都会跟着变动,所以他们是一个单独的 pod。

也就是说,该 Flutter Module 一共有三个 git 仓库:

1. Flutter Module 项目的仓库(编写代码等) 2. Flutter Module 打包出来的 frameworks(不包含 Flutter.framework) 3. Flutter.framework 仓库

这样的好处就是在我们编写完代码,运行 sh 文件的时候,不用去下载一个四五百兆的 flutter 引擎,脚本速度提升很快,并且其他的 iOS 项目也可以引用。

接着改一下 flutter-lib.podspec 文件,

7ju6jaZ.jpg!web

把这一行改成如下:

p = Dir::open("ios_frameworks")

arr = Array.new

p.each do |f|

if f == '.' || f == '..'

else

arr.push('ios_frameworks/'+f)

end

end

s.ios.vendored_frameworks = arr

这样就完成了引入所有的 frameworks。

5. 总结

到这里 Flutter Module 就完全引入到了现有的 iOS 工程中,关于如何运行代码,可以去 官方文档 - Adding a Flutter screen to an iOS app [5] 中查找。

这样集成的方案,感觉是目前最方便的了。(如有更佳方案,烦请告知)

Flutter 端写完代码直接运行 ./build_module.sh 就可以了。

iOS 端直接 pod install ,超级简单。

MzMZNn2.jpg!web

如有缺陷,希望大家提出,共同学习!

MnMbaiz.jpg!web

References

[1] 把flutter作为framework添加到已存在的iOS中:  https://www.kikt.top/posts/flutter/exists/add-flutter-to-ios/

[2] Flutter 官网 - Adding to an iOS app:  https://flutter.dev/docs/development/add-to-app/ios/project-setup

[3] shared_preferences:  https://pub.dev/packages/shared_preferences

[4] caijinglong 大佬的博客查看解决办法。:  https://www.kikt.top/posts/flutter/exists/add-flutter-to-ios/#使用-cocoapod-管理原生工程

[5] 官方文档 - Adding a Flutter screen to an iOS app:  https://flutter.dev/docs/development/add-to-app/ios/add-flutter-screen?tab=vc-objective-c-tab


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK