新增 iOS 應用擴充套件
本指南將向您展示如何將 iOS 應用擴充套件與 Flutter 應用結合使用。
概述
#iOS 應用擴充套件允許您在 iOS 應用之外擴充套件功能。您的應用可以顯示為主螢幕小部件,或者您可以將應用的部分功能提供給其他應用使用。
在以下示例中,當用戶在 iOS 照片應用中選擇要共享的照片時,“Example App With Extension”這個 Flutter 應用會顯示在照片應用的分享表中。

為您的 Flutter 應用新增 iOS 應用擴充套件
#如果您想將 Flutter 應用與 iOS 作業系統整合,可以為您的 Flutter 專案新增 iOS 應用擴充套件。為了實現無縫的工作流程,以下步驟將展示如何為名為 example_app_with_extension 的新 Flutter 應用新增一個 分享 應用擴充套件,但您也可以從現有專案開始。
在控制檯中,建立一個名為
example_app_with_extension的新 Flutter 專案。flutter create example_app_with_extension在控制檯中,開啟
example_app_with_extension專案的 Xcode 工作區。cd example_app_with_extension && open ios/Runner.xcworkspace在 Xcode 中,新增一個名為
Share的應用擴充套件,並將其命名為ShareExtension。在 Xcode 選單欄中,選擇 **檔案** > **新建** > **目標**。
新增 **分享擴充套件**。
在 **名稱** 欄位中,輸入 **ShareExtension**。
點選 Finish(完成)。
在出現的 **啟用…方案** 對話方塊中,選擇 **啟用**。
在 Xcode 中,更改構建過程的順序。
開啟 **專案導航器** (**檢視** > **導航器** > **專案**)。
在 **專案導航器** 的頂部,選擇 **Runner**。
在主視窗的 **TARGETS** 下,選擇 **Runner**。
開啟 **構建階段** 選項卡。
將 **嵌入 Foundation 擴充套件** 拖到 **執行指令碼** 的上方。
請確保您的 **最低部署** iOS 值設定正確,並且在 **Runner** 和 **ShareExtension** 中都匹配。
開啟 **專案導航器** (**檢視** > **導航器** > **專案**)。
在 **專案導航器** 的頂部,選擇 **Runner**。
在主視窗的 **TARGETS** 下,選擇 **Runner**。
在 **通用** 選項卡上,檢查您的 **最低部署** 下拉選單值,確保它與 **ShareExtension** > **通用** 選項卡上的值相匹配。
在控制檯中,執行以下命令以重新構建您的 iOS 應用。
flutter build ios --config-only
當您新增新的應用擴充套件時,Xcode 會根據您選擇的模板生成示例程式碼。有關生成的程式碼和 WidgetKit 的更多資訊,請參閱 Apple 的應用擴充套件文件。
測試 iOS 應用擴充套件
#在將應用擴充套件新增到 Flutter 專案後,您可以使用模擬器或物理裝置對其進行測試。如果您在除錯模式下測試擴充套件,則必須使用 iOS 模擬器。
以下步驟假定您使用的是 新增 iOS 應用擴充套件中的示例應用程式和分享擴充套件。
在 Xcode 中,為您的專案新增一個應用擴充套件。
在控制檯中,使用以下命令執行您的 iOS 應用。
flutter run在模擬器中,測試您的應用擴充套件。
啟動支援分享擴充套件的應用,例如照片應用。
選擇一張照片,點選分享按鈕,然後點選您應用的分享擴充套件圖示。
為您的專案新增一個應用擴充套件。
在控制檯中,以釋出模式執行您的 Flutter 應用。
flutter run --release在您的裝置上,測試您的應用擴充套件。
啟動支援分享擴充套件的應用,例如照片應用。
選擇一張照片,點選分享按鈕,然後點選您應用的分享擴充套件圖示。
與 iOS 應用擴充套件互動的更多方法
#Flutter 應用與 iOS 應用擴充套件的互動方式與 UIKit 或 SwiftUI 應用相同。包含的應用和應用擴充套件不直接通訊。當裝置使用者與擴充套件互動時,包含的應用可能未執行。應用和您的擴充套件可以讀取和寫入共享資源,或使用更高級別的 API 進行通訊。
使用更高級別的 API
#某些擴充套件具有 API。例如,Core Spotlight 框架會索引您的應用,允許使用者透過 Spotlight 和 Safari 進行搜尋。WidgetKit 框架可以觸發主螢幕小部件的更新。
為了簡化您的應用與擴充套件之間的通訊,Flutter 外掛封裝了這些 API。要查詢封裝了擴充套件 API 的外掛,請檢視 利用 Apple 的系統 API 和框架 或在 pub.dev 上搜索。
共享資源
#要在您的 Flutter 應用和應用擴充套件之間共享資源,請將 Runner 應用目標和擴充套件目標放在同一個 App Group 中。
新增目標到 App Group
在 Xcode 中開啟目標設定。
導航到 **簽名與功能** 選項卡。
選擇 **+ 功能**,然後選擇 **App Groups**。
從兩個選項中選擇要將目標新增到的 App Group。
- 從列表中選擇一個 App Group。
- 點選 **+** 新增一個新的 App Group。

當兩個目標屬於同一個 App Group 時,它們可以讀取和寫入同一個源。選擇以下任一資料來源:
- 鍵/值:使用
shared_preference_app_group外掛在同一個 App Group 內讀取或寫入UserDefaults。 - 檔案:使用
path_provider外掛提供的 App Group 容器路徑來 讀取和寫入檔案。 - 資料庫:使用
path_provider外掛提供的 App Group 容器路徑,並使用sqflite外掛建立一個數據庫。
安排後臺更新
#後臺任務提供了一種透過程式碼更新擴充套件的方式,而不管您的應用狀態如何。
要從您的 Flutter 應用排程後臺任務,請使用 workmanager 外掛。
新增深度連結
#您可能希望將使用者從應用擴充套件引導到 Flutter 應用中的特定頁面。要開啟應用中的特定路由,您可以使用 深度連結。
新增可滾動列表
#預設情況下,Flutter 檢視在 分享 擴充套件中不處理滾動事件。要支援分享擴充套件中的可滾動列表,請遵循 這些說明。
在 iOS 應用擴充套件中開啟 Flutter 應用
#您可以透過 FlutterViewController 直接在某些 iOS 應用擴充套件(如 分享 擴充套件)中開啟您的 Flutter 應用。
在以下示例中,名為 Example App With Extension 的 Flutter 應用在分享擴充套件中開啟,允許使用者在應用之間共享內容。

使用以下步驟在 分享 應用擴充套件中顯示 Flutter 應用。在此示例中,應用擴充套件方案名為 ShareExtension,Flutter 應用方案名為 Runner,Flutter 應用名為 Example App With Extension。
如果您還沒有為 Flutter 應用新增擴充套件,請 新增一個擴充套件。
在控制檯中,導航到您的 Flutter 專案目錄,然後使用以下命令在 Xcode 中開啟您的專案。
open ios/Runner.xcworkspace在 Xcode 中,停用使用者指令碼沙盒。
開啟 **專案導航器** (**檢視** > **導航器** > **專案**)。
在主視窗的 **TARGETS** 下,選擇 **ShareExtension**。
開啟 **構建設定** 選項卡。
導航到 **構建選項**。
將 **使用者指令碼沙盒** 設定為 **否**。
在 Xcode 中,將預操作新增到
ShareExtension方案。開啟 **管理方案** 視窗 (**產品** > **方案** > **管理方案**)。
選擇 ShareExtension 方案並進行編輯。
展開 **構建** 選項卡。
選擇 **預操作**。
點選 **+**,然後選擇 **新建執行指令碼操作**。
在 **提供構建設定來自** 下拉列表中,選擇 **ShareExtension**。
在 **Shell** 文字欄位中,輸入:
/bin/sh "$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" prepare點選 **關閉**。
在 Xcode 中,共享構建配置。
開啟 **專案導航器** (**檢視** > **導航器** > **專案**)。
在主視窗的 **PROJECT** 下,選擇 **Runner**。
開啟 **資訊** 選項卡。
展開 **配置**。
展開 **Debug**,並將 **ShareExtension** 的值更新為與 **Runner** 的值相匹配。
對 **Profile** 和 **Release** 重複上一步。
完成後,請確保配置看起來與以下內容相似。

(可選) 在 Xcode 中,根據需要用擴充套件類替換任何故事板檔案。
開啟 **專案導航器** (**檢視** > **導航器** > **專案**)。
選擇 **Runner** > **ShareExtension** > **Info**。
展開 **資訊屬性列表**。
刪除 **NSExtensionMainStoryboard** 鍵。
新增 **NSExtensionPrincipalClass** 鍵。
為
NSExtensionPrincipalClass鍵新增以下值之一:- (Swift) **ShareExtension.ShareViewController**
- (Objective-C) **ShareViewController**
在 Xcode 中,更新
ShareViewController以使用FlutterViewController。開啟 **專案導航器** (**檢視** > **導航器** > **專案**)。
選擇 **Runner** > **ShareExtension** > **ShareViewController**。
更新
ShareViewController以使用FlutterViewController類。
import UIKit
import Flutter
class ShareViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
showFlutter()
}
func showFlutter() {
let flutterEngine = FlutterEngine(name: "my flutter engine")
flutterEngine.run()
let flutterViewController = FlutterViewController(engine: flutterEngine, nibName: nil, bundle: nil)
addChild(flutterViewController)
view.addSubview(flutterViewController.view)
flutterViewController.view.frame = view.bounds
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
self.extensionContext?.cancelRequest(
withError: NSError(domain: Bundle.main.bundleIdentifier!, code: 0))
}
}@import Flutter;
@import UIKit;
@interface ShareViewController : UIViewController
@end#import "ShareViewController.h"
@import Flutter;
@implementation ShareViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self showFlutter];
}
- (void)showFlutter {
FlutterEngine *flutterEngine = [[FlutterEngine alloc] initWithName:@"my flutter engine"];
[flutterEngine run];
FlutterViewController *flutterViewController =
[[FlutterViewController alloc] initWithEngine:flutterEngine nibName:nil bundle:nil];
[self addChildViewController:flutterViewController];
[self.view addSubview:flutterViewController.view];
flutterViewController.view.frame = self.view.bounds;
}
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
[self.extensionContext cancelRequestWithError:[NSError errorWithDomain:NSBundle.mainBundle.bundleIdentifier code:0 userInfo:nil]];
}
@end註冊外掛
#使用以下步驟為應用擴充套件註冊外掛。在此示例中,應用擴充套件方案名為 ShareExtension,Flutter 應用方案名為 Runner,Flutter 應用名為 Example App With Extension。
如果您還沒有為 Flutter 應用新增擴充套件,請 新增一個擴充套件。
在 Xcode 中,將
GeneratedPluginRegistrant.m新增到應用擴充套件目標。開啟 **專案導航器** (**檢視** > **導航器** > **專案**)。
在主視窗的 **TARGETS** 下,選擇 **ShareExtension**。
開啟 **構建階段** 選項卡。
展開 **編譯原始檔**。
點選 **+**。
在“選擇要新增的項”對話方塊的列表中,選擇 **GeneratedPluginRegistrant.m**。
點選 **新增**。
(僅限 Swift) 在 Xcode 中,更新
SWIFT_OBJC_BRIDGING_HEADER構建設定。開啟 **專案導航器** (**檢視** > **導航器** > **專案**)。
在主視窗的 **TARGETS** 下,選擇 **ShareExtension**。
開啟 **構建設定** 選項卡。
選擇 **所有** 過濾器。
導航到 **Swift 編譯器 - 通用**,並將 **Objective-C 橋標頭檔案** 鍵的值更改為 Runner/Runner-Bridging-Header.h。
在 Xcode 中,更新
ShareViewController的程式碼以註冊GeneratedPluginRegistrant.h。開啟 **專案導航器** (**檢視** > **導航器** > **專案**)。
選擇 **Runner** > **ShareExtension** > **ShareViewController**。
更新
ShareViewController檔案以使用GeneratedPluginRegistrant.h。
// Add this inside `showFlutter()` at the top
GeneratedPluginRegistrant.register(with: flutterEngine)// Add this import at the top
#import "GeneratedPluginRegistrant.h"// Add this after [flutterEngine run]
[GeneratedPluginRegistrant registerWithRegistry:flutterEngine];- (Xcode) 使用模擬器測試您的應用。
約束
#您必須使用 iOS 模擬器在除錯模式下測試您的擴充套件。
Flutter 對在物理裝置上以除錯模式執行構建了擴充套件 UI 的應用擴充套件的支援不完全,因為物理裝置可能會耗盡記憶體。
iOS 應用擴充套件的記憶體有限。建議僅在應用擴充套件支援至少 100MB 記憶體時修改應用擴充套件的 UI。
在 iOS 應用擴充套件中呼叫 Dart 程式碼/渲染 Flutter 內容
#home_widget 包提供了大量功能,包括允許以下操作:
使用 Dart 程式碼在應用擴充套件中 響應使用者輸入。
在應用擴充套件中 將 Flutter 小部件渲染 為影像。
在 iOS 上 儲存和檢索資料(來自
UserDefaults)。
其他資源
#有關將應用擴充套件與 Flutter iOS 應用結合使用的分步說明,請檢視 為 Flutter 應用新增主螢幕小部件 Codelab。
要了解有關將 Flutter 螢幕新增到 iOS 應用的各種方法的更多資訊,請參閱 將 Flutter 螢幕新增到 iOS 應用。