【Flutter】iOS混搭Flutter
![【Flutter】iOS混搭Flutter](/content/images/size/w2000/2021/11/be5a22d5d9a2a4e790f60eda83b7bec1-thumb.jpg)
打從 Swift 出來之前(等等,明明是個 Android 工程師,怎麼跑來弄 Swift 呢?),就有許多的跨平台方案被提了出來,PhoneGap、Xamarin,等等的(完全暴露年紀),原先對這些方案都抱持著嗤之以鼻的態度,畢竟效能低落、開發成本也沒有比較低,對於雙平台還需各別處理一些東西,能省下的工其實也沒多少。直到最近碰上了 Flutter...
雖然說 Flutter 也不能解決所有跨平台的問題,但至少對於畫出雙平台一致的畫面,產生一樣的使用者經驗還是可以的,並且擁有豐富的套件庫,很多效果基本上不用自己硬寫,找一下套件修改一下就可以直接使用了。
這篇主要講的是如何把寫好的 Flutter 專案整合進 iOS 專案裡面,讓兩者可以交互使用,所以會先假設大家的環境都已配置完成,並有一個以可以執行的 Flutter 專案。那麼,就開始吧!
#方案選擇
根據 Flutter 官網,要將 Flutter 整合進 iOS 專案裡面有三種選擇
- 利用 CocoPods 跟 Flutter SDK
- 將 Flutter 專案打包成 Framework 供 iOS 專案叫用
- 利用 CocoPods 在 iOS 專案和 Flutter 中內嵌應用和外掛
這邊我們用看似比較簡單的 Framework 方式。
#產出 Framework
首先,打開 cmd 切換到你的 Flutter 專案目錄底下,並輸入以下指定讓 Flutter 來產出專案的 Framework 檔案,其中 output 為你希望產出的檔案放在哪裡,這邊我設定在桌面的 flutter_framework 資料夾下:
flutter build ios-framework --output=/Users/jeremy/Desktop/flutter_framework
而當你看到下面畫面,表示 Framework 已經順利產生完成,接著就可以把產出的檔案直接複製進 iOS 的專案底下,然後就可以打開 Xcode 來進行整合的部分。
💪 Building with sound null safety 💪
Building frameworks for com.jeremyhuang.flutter in debug mode...
├─Copying Flutter.xcframework... 343ms
├─Building App.xcframework... 20.3s
├─Building plugins... 15.4s
└─Moving to ../../flutter_framework/Debug 105ms
Building frameworks for com.jeremyhuang.flutter in profile mode...
├─Copying Flutter.xcframework... 243ms
├─Building App.xcframework... 65.0s
├─Building plugins... 16.5s
└─Moving to ../../flutter_framework/Profile 115ms
Building frameworks for com.jeremyhuang.flutter in release mode...
├─Copying Flutter.xcframework... 1,171ms
├─Building App.xcframework... 62.0s
├─Building plugins... 16.6s
└─Moving to ../../flutter_framework/Release 175ms
Frameworks written to /Users/jeremy/Desktop/flutter_framework.
#整合 iOS 專案及 Flutter Framework
接著打開 Xcode,並切換到目標 target 的 Build Settings > Build Phases > Link Binary With Libraries 部分,這時候可以直接將剛剛產出的 flutter_framework 裡面 Release (如果要 build 在模擬器上則是要用 Debug 的)底下的 Frameworks,以拖拉的方式拖進 Xcode 裡的 Link Binary With Libraries,如下圖所示。
![](https://blog.jeremyhuang.com/content/images/2021/11/-----2021-11-04---11.18.30.png)
而下方的 Embed Frameworks 也一樣要加入這些 Frameworks ,直接點選下方的加號把 Frameworks 都選起來就可以了。
![](https://blog.jeremyhuang.com/content/images/2021/11/-----2021-11-04---11.26.18.png)
如果找不到 Embed Frameworks 的話,可能要先切到 General 頁籤,並把 Frameworks, Libraries, and Embedded Content 底下的 Embed 類別改成 Embed & Sign,設定完再切回 Build Phases 頁籤,應該就會看到了。
![](https://blog.jeremyhuang.com/content/images/2021/11/-----2021-11-04---11.30.21.png)
下一步我們將頁籤切換到 Build Settings,找到 Search Paths 並將 Frameworks 的路徑加入到 Framework Search Paths 裡,我這邊填入的是 $(PROJECT_DIR)/Flutter/Release/
。
![](https://blog.jeremyhuang.com/content/images/2021/11/-----2021-11-04---11.24.24.png)
#添加 Flutter 畫面
準備就緒後就可以讓 iOS 專案呼叫 Flutter 的畫面起來了,這邊希望一開 App 的時候就可以跳出 Flutter 的畫面為目標。首先打開 AppDelegate.swift 檔案,先將 Flutter import 進來,創建 FlutterEngine ,並在 application() 裡把他 run 起來。
![](https://blog.jeremyhuang.com/content/images/2021/11/-----2021-11-04---11.42.57.png)
再來,打開 ViewController.swift 檔案,一樣先 import flutter,接著要利用 FlutterViewController 來將畫面呈現,如下所示:
![](https://blog.jeremyhuang.com/content/images/2021/11/-----2021-11-04---11.47.33.png)
至此,可以先把程式跑起來看看有沒有問題。
#GeneratedPluginRegistrant
如果你有使用一些插件的話,在 build 的時候可能會噴 MissingPluginException 的錯誤,這時候需要回到剛剛 Flutter 產出的那包 Frameworks 資料夾下,找到 GeneratedPluginRegistrant.h 及 GeneratedPluginRegistrant.m 兩個檔案,一樣用拖拉的方式,拖拉進 Xcode 左側的目錄結構裡,這時候 Xcode 應該會自動產生一個 ${Project_Name}-bridging-Header.h 的檔案,沒有的話就自己建立一個,並在裡面寫上:
#import "GeneratedPluginRegistrant.h"
接著回到 AppDelegate.swift 檔案,在剛剛的 flutterEngine.run(); 下面多加一行:
GeneratedPluginRegistrant.register(with: self.flutterEngine);
如此一來,再重新 build 一次應該就可以了。至此,大功告成 🎉