本篇文章大幅參考了 caijinglong 大佬的總結文章: 把flutter作為framework新增到已存在的iOS中
用 Flutter 來開發,從來都不可能是新開的一個純 Flutter 專案,很大一部分都是 老專案接入 Flutter 來混編。
在 Flutter 官網 - Adding to an iOS app 這裡,官方也給出了一些將 Flutter 整合進入現有 iOS 專案的方法。但是,這些都多多少少的不符合我們的需求。
1. 從 Flutter Module 說起
想要把 Flutter 整合進現有 iOS 專案,我們就必須使用 Flutter Module。
那就先用命令建立一個 Flutter Module:flutter create --template module flutter_test_module
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:
- Flutter.framework
- App.framework
- FlutterPluginRegistrant.framework (如果有用到原生的外掛 - 非純 dart 編寫)
- Pods_Runner.framework(如果有用到原生的外掛 - 非純 dart 編寫)
- *.framework(外掛的 framework)
下面繼續整合。
Flutter Module 建立完成後,先來給 iOS 打個包,命令如下:flutter build ios --release --no-codesign
。
然後看一下打包出來的東西,路徑為 build->ios->Release-iphoneos
:
如果有第三方庫的話,這裡面應該是有上面說的 3、4、5 的 framework,但是我們剛建立專案,什麼都沒有加,所以是沒有任何 framework的。
然後去 .ios/Flutter
裡找 1、2:
但是我們寫程式不可能什麼外掛都不用,所以加上一個shared_preferences,再來打包看一下 build 資料夾:
可以看到確實出現了我們上面說的 3、4、5 framework,這樣我們所需的 framework 全部集齊。
3. 使用 cocoapods + git 來管理
因為 caijinglong 大佬 文章內說:
因為找遍了 podfile 的相關文件, 沒有找到可以直接引用 framework 的方式
所以需要一個 pod 庫作為"中轉”
所以我們就要 跟著做!
使用命令 pod lib create flutter-lib
來建立一個名為 flutter-lib的私有庫。
建立完成之後,開啟 flutter-lib.podspec
,在 end
前面加入一行:
接著我們在該資料夾內建立一個名為 ios_frameworks
的資料夾,把我們剛才的那麼多 framework 全都貼上過來。
這個時候我們的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. 編寫指令碼自動處理
上面都是手動來處理的,包括打包->移動檔案->上傳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 倉庫:
- Flutter Module 專案的倉庫(編寫程式碼等)
- Flutter Module 打包出來的 frameworks(不包含 Flutter.framework)
- Flutter.framework 倉庫
這樣的好處就是在我們編寫完程式碼,執行 sh 檔案的時候,不用去下載一個四五百兆的 flutter 引擎,指令碼速度提升很快,並且其他的 iOS 專案也可以引用。
接著改一下 flutter-lib.podspec
檔案,
把這一行改成如下:
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 中查詢。
這樣整合的方案,感覺是目前最方便的了。(如有更佳方案,煩請告知)
Flutter 端寫完程式碼直接執行 ./build_module.sh
就可以了。
iOS 端直接 pod install
,超級簡單。
如有缺陷,希望大家提出,共同學習!?