作者:CaffreySun
連結:https://juejin.im/post/5c3ae5ef518825242165c5ca
本文來實現一個靈活、無侵入、低耦合的 iOS Flutter 混合工程。我們希望混合開發至少得保證如下特點:
-
對Native工程無侵入
-
對Native工程零耦合
-
不影響Native工程的開發流程與打包流程
-
易本地除錯
一、Flutter 提供的 Native Flutter 混合工程方式
Flutter 官方提供的混合工程搭建方法:Add Flutter to existing apps文章中介紹瞭如何在現有 App 裡加入Flutter,下麵進行逐步介紹一下
1、建立 Flutter 工程
請自行 百度/Google Flutter 安裝教程,安裝Flutter。然後到任意目錄下執行flutter create -t module my_flutter
,”my_flutter” 是要建立的 Flutter 工程的名稱。
2、透過 Cocoapods 將 Flutter 引入 現有 Native 工程
在Podfile新增以下下程式碼
flutter_application_path = "xxx/xxx/my_flutter"
eval(File.read(File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')), binding)
然後執行pod install
3、修改 Native 工程
開啟Xcode工程,選擇要加入 Flutter App 的 target,選擇 Build Phases,點選頂部的 + 號,選擇 New Run Script Phase,然後輸入以下指令碼
"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" build
"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" embed
二、分析 Native Flutter 混合工程
按照上面三個步驟進行逐一分析每一步的問題,並提供最佳化方案。
1、建立 Flutter 工程
這一步首先在自己電腦上安裝 Flutter,然後使用flutter create。這裡就存在問題,在團隊開發中每個人安裝的 Flutter 版本可能並不同,這樣會出現Dart層Api相容性或Flutter虛擬機器不一致等問題。在團隊協作中一定要保證 Flutter 工程依賴相同的 Flutter SDK,所有需要一個工具在執行 flutter
指令時可以根據當前 Flutter 工程使用對應版本的 Flutter SDK,目前有一個名叫flutter_wrapper的工具,使用 flutterw
代替
指令,工具會自動將 Flutter SDK 放在當前 Flutter 工程目錄下,並執行當前工程中的 flutter
flutter
命令,這樣就不再依賴本地電腦安裝的 Flutter SDK。
flutter_wrapper使用:
-
flutter create建立 Flutter 工程,這裡使用的是本地的 Flutter SDK
-
進入 Flutter 工程目錄安裝 ‘flutter_wrapper’,執行
sh -c "$(curl -fsSL https://raw.githubusercontent.com/passsy/flutter_wrapper/master/install.sh)"
-
此後在當前 Flutter 工程需要使用
flutter
./flutterw
來代替
2、透過 Cocoapods 將 Flutter 引入 現有 Native 工程
這一步在 Podfile 裡添加里一個 ‘podhelper.rb’ ruby 指令碼,指令碼會在 pod install/update
時執行,指令碼主要做4點事情:
-
解析 ‘Generated.xcconfig’ 檔案,獲取 Flutter 工程配置資訊,檔案在’my_flutter/.ios/Flutter/’目錄下,檔案中包含了 Flutter SDK 路徑、Flutter 工程路徑、Flutter 工程入口、編譯目錄等。
-
將 Flutter SDK 中的
Flutter.framework
透過 pod 新增到 Native 工程。 -
將 Flutter 工程依賴的外掛透過 pod 新增到 Native 工程,因為有些外掛有 Native 部分程式碼。
-
使用
post_install
這個 pod hooks 來關閉 Native 工程的 bitcode,並將 ‘Generated.xcconfig’ 檔案加入 Native 工程。
這一步存在問題是,’podhelper.rb’指令碼是透過一個本地 Flutter 工程路徑’flutter_application_path’來讀取,在團隊協作中我們很難保證每個人的本地 Flutter 工程路徑都一樣,在同步程式碼時大家可能都要頻繁修改’flutter_application_path’變數,這樣很不友好。
解決這個問題的思路就是將 Flutter 工程放在當前 Native 工程的目錄下,我們可以再加入一個 ruby 指令碼,在每次執行 pod install/update
時,將 Flutter 工程從 git 上拉取一份放在當前目錄下,這樣 Flutter 工程的路徑就統一了。大致程式碼如下:
flutter_application_path = __dir__ + "/.flutter/app"
`git clone git://xxxx/my_flutter.git #{flutter_application_path}`
# 如果想要除錯本地的 Flutter 工程,就把下麵這行註釋放開
# flutter_application_path = "xxx/xxx/my_flutter"
eval(File.read(File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')), binding)
上述程式碼只是臨時程式碼,為了演示將 Flutter 工程放在當前目錄下這個思路,後面會有完整的實現程式碼。
3. 修改 Native 工程
這裡執行了一個’xcode_backend.sh’指令碼的兩個命令build、embed,兩個命令分別的作業是:
-
build: 根據當前 Xcode 工程的 ‘configuration’ 和其他編譯配置編譯 Flutter 工程,’configuration’通常為’debug’或者’release’
-
embed: 將 build 出來的 framework、資源包放入 Xcode 編譯目錄,並簽名 framework
這裡存在的問題是:Flutter 工程依賴 Native工程來執行編譯,並影響Native工程的開發流程與打包流程。
通常 ‘configuration’ 裡不止有 ‘debug’ 或者 ‘release’,可能會有自定義的名稱,如果我們使用自定義的 ‘configuration’ 編譯,那麼 xcode_backend.sh build就會執行失敗。因為Flutter 編譯樣式是透過 ‘configuration’ 獲取的,Flutter 支援 Debug、Profil、Release 三種編譯樣式,而我們自定義的名稱不在這三種之中,Flutter 就不知道該怎麼編譯。
每次 Native 編譯時 Flutter 就需要編譯,其實是產生了相互依賴:Flutter 編譯依賴 Native 編譯環境,Native 依賴 Flutter 編譯透過。
我們希望做到:Native 依賴 Flutter 編譯出來的產物,並且保留依賴 Flutter 原始碼進行除錯的能力。
實現這個標的我們需要兩部分:
-
第一部分:Flutter 工程裡建立一個打包指令碼,可以一鍵產生 Flutter 工程產物;
-
第二部分:在 Native 工程獲取 FLutter 工程的編譯產物,並透過 pod 新增到工程;並且保留依賴 Flutter 工程原始碼的功能。
三、實現 Native Flutter 混合工程
下麵我們來實現上文提到的兩個部分
第一部分實現“打包指令碼”
這一部分我們需要實現指令碼自動打包 Flutter 工程,拆分一下這個指令碼流程,大致分為一下幾個步驟:
-
檢查 Flutter 環境,拉取 Flutter plugin
-
編譯 Flutter 工程產物
-
複製 Flutter 外掛中的 Native 程式碼
-
將產物同步到產物釋出的伺服器
下麵來一步一步的分析並實現每一步:
(1) 檢查 Flutter 環境,拉取 Flutter plugin
這一步做的工作是檢查是否安裝了 ‘flutter_wrapper’,如果安裝則進行安裝,然後執行 ./flutterw packages get
,Shell程式碼如下:
flutter_get_packages() {
echo "================================="
echo "Start get flutter app plugin"
local flutter_wrapper="./flutterw"
if [ -e $flutter_wrapper ]; then
echo 'flutterw installed' >/dev/null
else
bash -c "$(curl -fsSL https://raw.githubusercontent.com/passsy/flutter_wrapper/master/install.sh)"
if [[ $? -ne 0 ]]; then
# 上一步指令碼執行失敗
echo "Failed to installed flutter_wrapper."
exit -1
fi
fi
${flutter_wrapper} packages get --verbose
if [[ $? -ne 0 ]]; then
# 上一步指令碼執行失敗
echo "Failed to install flutter plugins."
exit -1
fi
echo "Finish get flutter app plugin"
}
(2) 編譯 Flutter 工程產物
這一步是指令碼的核心,主要邏輯和上文中’xcode_backend.sh build’類似,大致程式碼如下:
# 預設debug編譯樣式
BUILD_MODE="debug"
# 編譯的cpu平臺
ARCHS_ARM="arm64,armv7"
# Flutter SDK 路徑
FLUTTER_ROOT=".flutter"
# 編譯目錄
BUILD_PATH=".build_ios/${BUILD_MODE}"
# 存放產物的目錄
PRODUCT_PATH="${BUILD_PATH}/product"
# 編譯出的flutter framework 存放的目錄
PRODUCT_APP_PATH="${PRODUCT_PATH}/Flutter"
build_flutter_app() {
echo "================================="
echo "Start Build flutter app"
# 建立目錄
mkdir -p -- "${PRODUCT_APP_PATH}"
# flutter 工程入口 dart檔案
local target_path="lib/main.dart"
# flutter sdk 目錄解析
local artifact_variant="unknown"
case "$BUILD_MODE" in
release*)
artifact_variant="ios-release"
;;
profile*)
artifact_variant="ios-profile"
;;
debug*)
artifact_variant="ios"
;;
*)
echo "ERROR: Unknown FLUTTER_BUILD_MODE: ${BUILD_MODE}."
exit -1
;;
esac
if [[ "${BUILD_MODE}" != "debug" ]]; then
# 非debug編譯樣式
# build fLutter app,output App.framework
${FLUTTER_ROOT}/bin/flutter --suppress-analytics
--verbose
build aot
--output-dir="${BUILD_PATH}"
--target-platform=ios
--target="${target_path}"
--${BUILD_MODE}
--ios-arch="${ARCHS_ARM}"
if [[ $? -ne 0 ]]; then
echo "Failed to build flutter app"
exit -1
fi
else
# debug編譯樣式直接使用編譯好的App.framework,
# 因為在 debug 樣式下 flutter 程式碼並沒有編譯成二進位制機器碼,而是在後續build bundle時被打包進資源包,
# 在'xcode_backend.sh'腳本里,這一步這裡只是編譯成一個App.framework空殼。
# 提前編譯好的原因是'xcode_backend.sh'指令碼執行和Xcode一起執行,所以執行時能獲取到Xcode設定的編譯配置,能正確的編譯出'App.framework',
# 而本指令碼不依賴Xcode執行,即便把'xcode_backend.sh'對應的程式碼複製出來也不能正確的編譯出'App.framework',除非我們能正確的配置編譯環境。
#
# 而我又不想那麼麻煩,選擇另闢蹊徑:
# 隨便建立了一個 Flutter 工程,
# 在debug樣式下,先在模擬器編譯執行一下,得到x86_64的App.framework,
# 再到真機執行一下,得到arm64/armv7的App.framework,
# 最後使用lipo命令將兩個App.framework合併,得到x86_64/arm64/armv7的App.framework,
# 這樣最後得到的App.framework在模擬器和真機都可以用
# 因為debug樣式下App.framework就是佔位的空殼,所以其他flutter工程一樣用
local app_framework_debug="iOSApp/Debug/App.framework"
cp -r -- "${app_framework_debug}" "${BUILD_PATH}"
fi
# copy info.plist to App.framework
app_plist_path=".ios/Flutter/AppFrameworkInfo.plist"
cp -- "${app_plist_path}" "${BUILD_PATH}/App.framework/Info.plist"
local framework_path="${FLUTTER_ROOT}/bin/cache/artifacts/engine/${artifact_variant}"
local flutter_framework="${framework_path}/Flutter.framework"
local flutter_podspec="${framework_path}/Flutter.podspec"
# copy framework to PRODUCT_APP_PATH
cp -r -- "${BUILD_PATH}/App.framework" "${PRODUCT_APP_PATH}"
cp -r -- "${flutter_framework}" "${PRODUCT_APP_PATH}"
cp -r -- "${flutter_podspec}" "${PRODUCT_APP_PATH}"
local precompilation_flag=""
if [[ "$BUILD_MODE" != "debug" ]]; then
precompilation_flag="--precompiled"
fi
# build bundle
${FLUTTER_ROOT}/bin/flutter --suppress-analytics
--verbose
build bundle
--target-platform=ios
--target="${target_path}"
--${BUILD_MODE}
--depfile="${BUILD_PATH}/snapshot_blob.bin.d"
--asset-dir="${BUILD_PATH}/flutter_assets"
${precompilation_flag}
if [[ $? -ne 0 ]]; then
echo "Failed to build flutter assets"
exit -1
fi
# copy Assets
cp -rf -- "${BUILD_PATH}/flutter_assets" "${PRODUCT_APP_PATH}/App.framework"
# setting podspec
# replace:
# 'Flutter.framework'
# to:
# 'Flutter.framework', 'App.framework'
sed -i '' -e $'s/'Flutter.framework'/'Flutter.framework', 'App.framework'/g' ${PRODUCT_APP_PATH}/Flutter.podspec
echo "Finish build flutter app"
}
(3) 複製 Flutter 外掛中的 Native 程式碼
Flutter 使用的各種外掛可能會包含 Native 程式碼,並且這些程式碼已經提供了podspec,可以使用 pod 直接引入。我們要做的就是把外掛的 Native 程式碼複製到產物目錄。Flutter 建立了一個給 Native 註冊外掛的 pod 庫 ‘FlutterPluginRegistrant’,這個也需要複製出來,在 Flutter 工程根目錄下有一個 .flutter-plugins 檔案,檔案內部記錄了外掛的名字和外掛的路徑,格式為 pugin_name=/xx/xx/xx
,解析這個檔案就可以得到外掛資訊,程式碼如下:
flutter_copy_packages() {
echo "================================="
echo "Start copy flutter app plugin"
local flutter_plugin_registrant="FlutterPluginRegistrant"
local flutter_plugin_registrant_path=".ios/Flutter/${flutter_plugin_registrant}"
echo "copy 'flutter_plugin_registrant' from '${flutter_plugin_registrant_path}' to '${PRODUCT_PATH}/${flutter_plugin_registrant}'"
cp -rf -- "${flutter_plugin_registrant_path}" "${PRODUCT_PATH}/${flutter_plugin_registrant}"
local flutter_plugin=".flutter-plugins"
if [ -e $flutter_plugin ]; then
OLD_IFS="$IFS"
IFS="="
cat ${flutter_plugin} | while read plugin; do
local plugin_info=($plugin)
local plugin_name=${plugin_info[0]}
local plugin_path=${plugin_info[1]}
if [ -e ${plugin_path} ]; then
local plugin_path_ios="${plugin_path}ios"
if [ -e ${plugin_path_ios} ]; then
if [ -s ${plugin_path_ios} ]; then
echo "copy plugin 'plugin_name' from '${plugin_path_ios}' to '${PRODUCT_PATH}/${plugin_name}'"
cp -rf ${plugin_path_ios} "${PRODUCT_PATH}/${plugin_name}"
fi
fi
fi
done
IFS="$OLD_IFS"
fi
echo "Finish copy flutter app plugin"
}
(4) 將產物同步到保留產物的伺服器
經過上面的幾個步驟後會生成一個產物目錄,這個目錄下會有幾個二級目錄,每個二級目錄裡都包含一個 podspec 檔案。
也就是說這個產物目錄裡存放的就是 cocoapods 庫,將目錄複製到 Native 工程,然後用 pod 'pod_name', :path=>'xx/xxx'
的形式取用就可以了。
有了產物後我們需要一個存放產物的地方, 大家可以去這個地方下載,這一步比較靈活,可以選擇將產物放在git倉庫、http伺服器、ftp伺服器等。我最終選擇將產物壓縮成 zip 上傳到 Maven 上,原因是為了和 Android Flutter 產物放在一個地方,並且 Maven 已成做好的產物版本管理。
Maven上傳程式碼比較簡單,這裡不再贅述,有興趣可以到文末的github倉庫檢視程式碼。
Flutter 工程版本設定是在工程目錄下的 ‘pubspec.yaml’ 檔案,打包指令碼讀取這個檔案來確定產物的版本。
最後這個指令碼使用方式為 ./build_ios.h -m debug
./build_ios.h -m release
,上文中沒有提到的一點是隻有 release 樣式編譯的包才會上傳的伺服器,debug 只是編譯到產物目錄。
第二步 Native 依賴 Flutter 產物
這部分我們需要實現獲取指定版本 Flutter 工程 release 產物,並整合到 Native 專案,並保留可以除錯 Flutter 工程的能力。
也是來拆分一下指令碼流程:
-
獲取 Flutter 工程產物
-
獲取 release 產物
-
獲取 debug 產物
-
-
透過 pod 引入 Flutter 工程產物
(1) 獲取 Flutter 工程產物
上文說到只有 release 產物放在了產物伺服器上,debug 只是編譯到產物目錄。不上傳 debug 的原因是,debug 階段就是開發階段,舉個不太恰當的例子:哪有開發階段就把包上傳 app store 的?也就代表這 release 的產物和 debug 的產物獲取邏輯不一樣,並且我們的指令碼支援兩種方式的切換,所以在 Podfile 新增如下程式碼:
# 設定要引入的 flutter app 的版本
FLUTTER_APP_VERSION="1.1.1"
# 是否進行除錯 flutter app,
# 為true時FLUTTER_APP_VERSION配置失效,下麵的三項配置生效
# 為false時FLUTTER_APP_VERSION配置生效,下麵的三項配置失效
FLUTTER_DEBUG_APP=false
# Flutter App git地址,從git拉取的內容放在當前工程目錄下的.flutter/app目錄
# 如果指定了FLUTTER_APP_PATH,則此配置失效
FLUTTER_APP_URL="git:/xxxx.git"
# flutter git 分支,預設為master
# 如果指定了FLUTTER_APP_PATH,則此配置失效
FLUTTER_APP_BRANCH="master"
# flutter本地工程目錄,絕對路徑或者相對路徑,如果有值則git相關的配置無效
FLUTTER_APP_PATH="../my_flutter"
eval(File.read(File.join(__dir__, 'flutterhelper.rb')), binding)
Podfile 其實就是 Ruby 程式碼,上面幾個由大寫字母組成的變數是全域性變數,最後一句程式碼的作用為讀取’flutterhelper.rb’裡的程式碼並執行,在’flutterhelper.rb’裡可以獲取到上面定義的全域性變數,根據這幾個變數做不同的操作,其中選擇使用 release 還是 debug 的程式碼如下:
if FLUTTER_DEBUG_APP.nil? || FLUTTER_DEBUG_APP == false
# 使用 flutter release 樣式
puts "開始安裝 release mode flutter app"
install_release_flutter_app()
else
# 存在debug配置,使用 flutter debug 樣式
puts "開始安裝 debug mode flutter app"
install_debug_flutter_app()
end
install_release_flutter_app
為操作 release 產物的函式,install_debug_flutter_app
為操作 debug 產物的函式。
處理 release 樣式主要就是獲取 release 產物,程式碼如下:
# 安裝正式環境環境app
def install_release_flutter_app
if FLUTTER_APP_VERSION.nil?
raise "Error: 請在 Podfile 裡設定要安裝的 Flutter app 版本 ,例如:FLUTTER_APP_VERSION='1.0.0'"
else
puts "當前安裝的 flutter app 版本為 #{FLUTTER_APP_VERSION}"
end
# 存放產物的目錄
flutter_release_path = File.expand_path('.flutter_release')
# 是否已經存在當前版本的產物
has_version_file = true
if !File.exist? flutter_release_path
FileUtils.mkdir_p(flutter_release_path)
has_version_file = false
end
# 存放當前版本產物的目錄
flutter_release_version_path = File.join(flutter_release_path, FLUTTER_APP_VERSION)
if !File.exist? flutter_release_version_path
FileUtils.mkdir_p(flutter_release_version_path)
has_version_file = false
end
# 產物包
flutter_package = "flutter.zip"
flutter_release_zip_file = File.join(flutter_release_version_path, flutter_package)
if !File.exist? flutter_release_zip_file
has_version_file = false
end
# 產物包下載完成標誌
flutter_package_downloaded = File.join(flutter_release_version_path, "download.ok")
if !File.exist? flutter_package_downloaded
has_version_file = false
end
if has_version_file == true
# 解壓
flutter_package_path = unzip_release_flutter_app(flutter_release_version_path, flutter_release_zip_file)
# 開始安裝
install_release_flutter_app_pod(flutter_package_path)
else
# 刪除老檔案
FileUtils.rm_rf(flutter_release_zip_file)
# 刪除標誌物
FileUtils.rm_rf(flutter_package_downloaded)
# 下載
download_release_flutter_app(FLUTTER_APP_VERSION, flutter_release_zip_file, flutter_package_downloaded)
# 解壓
flutter_package_path = unzip_release_flutter_app(flutter_release_version_path, flutter_release_zip_file)
# 開始安裝
install_release_flutter_app_pod(flutter_package_path)
end
end
unzip_release_flutter_app
為解壓zip格式產物的函式,download_release_flutter_app
為從 Maven 下載產物的函式,這兩個比較簡單,詳細程式碼請看文末 github 倉庫。install_release_flutter_app_pod
為透過 pod 將產物新增到 Native 的函式,後面會詳細介紹。
處理 debug 樣式的操作為,獲取 Flutter 工程原始碼,執行 build_ios.sh -m debug
進行打包,然後得到 debug 產物目錄,詳細程式碼如下:
# 安裝開發環境app
def install_debug_flutter_app
puts "如果是第一次執行開發環境Flutter專案,此過程可能會較慢"
puts "請耐心等️待☕️️️️️☕️☕️
"
# 預設Flutter App 目錄
flutter_application_path = __dir__ + "/.flutter/app"
flutter_application_url = ""
flutter_application_branch = 'master'
# 指定了FLUTTER_APP_PATH就用原生代碼,複製從git拉取
if FLUTTER_APP_PATH != nil
File.expand_path(FLUTTER_APP_PATH)
if File.exist?(FLUTTER_APP_PATH)
flutter_application_path = FLUTTER_APP_PATH
else
flutter_application_path = File.expand_path(FLUTTER_APP_PATH)
if !File.exist?(flutter_application_path)
raise "Error: #{FLUTTER_APP_PATH} 地址不存在!"
end
end
puts "
Flutter App路徑: "+flutter_application_path
else
if FLUTTER_APP_URL != nil
flutter_application_url = FLUTTER_APP_URL
if FLUTTER_APP_BRANCH != nil
flutter_application_branch = FLUTTER_APP_BRANCH
end
else
raise "Error: 請在'Podfile'裡增加Flutter App git地址配置,配置格式請檢視'flutterhelper.rb'檔案"
end
puts "
拉取 Flutter App 程式碼"
puts "Flutter App路徑: "+flutter_application_path
update_flutter_app(flutter_application_path, flutter_application_url, flutter_application_branch)
end
puts "
編譯 Flutter App"
# PUB_HOSTED_URL FLUTTER_STORAGE_BASE_URL 為了加快速度,使用國內映象地址
`export PUB_HOSTED_URL=https://pub.flutter-io.cn &&
export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn &&
cd #{flutter_application_path} &&
#{flutter_application_path}/build_ios.sh -m debug`
if $?.to_i == 0
flutter_package_path = "#{flutter_application_path}/.build_ios/debug/product"
# 開始安裝
install_release_flutter_app_pod(flutter_package_path)
else
raise "Error: 編譯 Flutter App失敗"
end
end
update_flutter_app
為從 git 拉取程式碼的函式也不贅述,詳情見文末 github 倉庫。
(2) 透過 pod 引入 Flutter 工程產物
上文兩個函式執行完成後,就得到了產物的存放目錄,下麵只需要引入到 Native 倉庫就可以了,也就是install_release_flutter_app_pod
函式,從程式碼如下:
# 將 Flutter app 透過 pod 安裝
def install_release_flutter_app_pod(product_path)
if product_path.nil?
raise "Error: 無效的 flutter app 目錄"
end
puts "將 flutter app 透過 pod 匯入到 工程"
Dir.foreach product_path do |sub|
if sub.eql?('.') || sub.eql?('..')
next
end
sub_abs_path = File.join(product_path, sub)
pod sub, :path=>sub_abs_path
end
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['ENABLE_BITCODE'] = 'NO'
end
end
end
end
如果要修改 release 產物版本,則設定FLUTTER_APP_VERSION
。如果想要 debug flutter,則設定 FLUTTER_DEBUG_APP=true
,如果除錯原生代碼則設定 FLUTTER_APP_PATH="../my_flutter"
,負責將 FLUTTER_APP_PATH註釋掉,配置
FLUTTER_APP_URL
FLUTTER_APP_BRANCH
。
四、總結
對照上文中提到的對混合工程的要求,總結一下:
-
Flutter 工程完全不依賴 Native 工程,而是透過 ‘build_ios.sh’ 指令碼進行編譯打包;
-
透過 pod 引入 Flutter 工程對 Native 也沒有浸入,不要在 Native 工程裡增加 Flutter 打包指令碼;
-
Native 開發工程師只需要執行
pod install
所有的 Flutter 依賴就都加入進工程,不需要工程師配置 Flutter 開發環境;也不影響 Native 打包; -
也保留了本地除錯 Flutter 工程的功能;
Github 倉庫:https://github.com/CaffreySun/iOS_Flutter_Hybrid_Project
朋友會在“發現-看一看”看到你“在看”的內容