新增 iOS App Clip target

這個指南介紹瞭如何手動新增另一個使用 Flutter 來渲染的 iOS App Clip target, 並將它整合到您現有的 Flutter 專案或 add-to-app 專案。

要檢視完整可用的範例,請參閱 GitHub 上的 App Clip 範例

步驟 1 - 開啟專案

開啟您的 iOS Xcode 工程,例如您的純 Flutter 專案中的 ios/Runner.xcworkspace

步驟 2 - 新增一個 App Clip 的 target

2.1

點選您專案的 Project Navigator 來顯示工程設定。

點選 target 列表底部的 + 來新增一個新的 target。

2.2

為您的新 target 選擇 App Clip 型別。

2.3

在對話方塊為您的新 target 輸入詳情。

選擇 Storyboard 作為介面。

選擇 UIKit App Delegate 作為生命週期。

選擇與您原來的 target 相同的程式語言

(換句話說,請勿為 Objective-C target 建立 Swift 型別的 App Clip target,反之亦然,以簡化設定。)

2.4

在接下來的對話方塊中,為新的 target 啟用 (activate) 一個新的 scheme。

步驟 3 - 移除不需要的檔案

3.1

在專案 Project Navigator 的新建立的 App Clip 組中,將除了 Info.plistApp Clip target.entitlements 以外的所有內容刪除。

移動檔案到廢紙簍。

3.2

如果您不使用 SceneDelegate.swift 檔案,移除在 Info.plist 中對應的參考。

開啟 App Clip 組中的 Info.plist。刪除 Application Scene Manifest 字典條目。

步驟 4 - 共享建構配置

對於 add-to-app 專案,此步驟不是必需的,因為 add-to-app 有自己的自訂建構配置和版本。

4.1

返回專案設定,現在選擇 Project 條目,而不是 Targets 裡的任何 target。

Info 選項卡頁中的 Configurations 可擴充組下,展開 DebugProfileRelease 條目。

每一個 App Clip target 的下拉選單的值都應該與常規應用 target 中的值相同。

這使您的 App Clip target 可以存取 Flutter 的必需建構設定。

4.2

在 App Clip 組的 Info.plist 檔案中,設定:

  • Build version string (short) to $(FLUTTER_BUILD_NAME)
  • Bundle version to $(FLUTTER_BUILD_NUMBER)

步驟 5 - 共享程式碼和資源

選項 1 - 共享所有東西

假設您的目標是在 App Clip 中顯示與普通應用相同的 Flutter UI,並共享相同的程式碼和資源。

對於以下每一個檔案: Main.storyboardAssets.xcassetsLaunchScreen.storyboardGeneratedPluginRegistrant.mAppDelegate.swift,(如果您是 Objective-C 還應該包括 Supporting Files/main.m)選擇檔案並且在檢查器中選擇第一個選項卡,並且在 Target Membership 選中 App Clip

選項 2 - 為 App Clip 自訂 Flutter 的啟動器

在這個例子中,不需要刪除在 步驟 3 中的任何東西。相對的,使用 iOS add-to-app APIs 的範本來自訂 Flutter 啟動器。可以參考範例 自訂 Flutter 路由

步驟 6 - 新增 App Clip 的關聯域名

這是一個 App Clip 開發的標準步驟。請檢視 蘋果官方文件

6.1

開啟 <app clip target>.entitlements 檔案。新增 Associated Domains 陣列。新增一行 appclips:<your bundle id> 到陣列中。

6.2

同樣的相關域名權利也需要新增到您的主應用程式中。

<app clip target>.entitlements 檔案從 App Clip 組複製到主應用程式組,並將其重新命名為與主目標相同的名稱,例如 Runner.entitlements

開啟檔案並刪除主應用程式授權檔案的 Parent Application Identifiers 條目(將該條目保留為 App Clip 的授權檔案)。

6.3

返回專案設定,選擇主應用 target,開啟 Build Settings 選項卡。設定 Code Signing Entitlements 的值為主應用建立的第二個授權檔案的相對路徑。

步驟 7 - 整合 Flutter

add-to-app 不需要這些步驟。

7.1

在您的 App Clip 的 target 的專案設定,開啟 Build Settings 選項卡。

Framework Search Paths 新增兩個內容:

  • $(inherited)
  • $(PROJECT_DIR)/Flutter

換句話說,與主應用程式 target 的建構設定相同。

7.2

如果是 Swift target,設定 Objective-C Bridging Header 建構配置為 Runner/Runner-Bridging-Header.h

換句話說,與主應用程式 target 的建構設定相同。

7.3

現在開啟 Build Phases 選項卡。點選 + 並且選擇 New Run Script Phase

拖動新的 phase 到 Dependencies phase。

展開新 phase 並將以下內容新增到指令碼:

/bin/sh "$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" build

簡單來說,與主應用程式 target 的建構設定相同。

這可以確保在執行 App Clip target 時編譯 Flutter 的 Dart 程式碼。

7.4

再次點選 + 並且選擇 New Run Script Phase。這是最後一個 phase。

這次新增如下內容:

/bin/sh "$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" embed_and_thin

簡單來說,與主應用程式 target 的建構設定相同。

這將確保您的 Flutter 應用程式和引擎嵌入到 App Clip bundle 中。

Step 8 - 整合外掛

8.1

在您的 Flutter 專案或是 add-to-app 的宿主專案中開啟 Podfile 檔案。

如果是完整的 Flutter 專案,替換下面這段程式碼:

target 'Runner' do
  use_frameworks!
  use_modular_headers!

  flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
end

為:

use_frameworks!
use_modular_headers!
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))

target 'Runner'
target '<name of your App Clip target>'

在檔案的開始,需要把 platform :ios, '9.0' 的註釋解除,並且為您的 2 個 target 設定最低可執行的 iOS 系統版本。

如果是 add-to-app,緊跟下面的程式碼:

target 'MyApp' do
  install_all_flutter_pods(flutter_application_path)
end

新增:

target 'MyApp' do
  install_all_flutter_pods(flutter_application_path)
end

target '<name of your App Clip target>'
  install_all_flutter_pods(flutter_application_path)
end

8.2

在命令列中,目前工作目錄需要是您的 Flutter 專案目錄,然後安裝 pod:

cd ios
pod install

執行

您現在可以在 Xcode 的 scheme 下拉中選擇並執行您的 App Clip target 了,選擇一個 iOS 14 的裝置並點選執行。

要從頭測試 App Clip 的啟動,您也可以檢視蘋果公司的文件 測試您的 App Clip 的啟動體驗

除錯和熱重載

不幸的是,由於網路許可權的原因,flutter attach 無法在 App clip 中自動發現 Flutter 會話。

為了除錯 App clip 並使用諸如熱重新載入之類別的功能,必須在執行應用後從 Xcode 中的控制檯輸出中查詢 Observatory URI。

您需要複製貼上它們到 flutter attach 來連線。

例如:

flutter attach --debug-uri <copied URI>