新增 iOS App 擴充套件
瞭解如何向 Flutter 應用新增 App 擴充套件
本指南向您展示如何在 Flutter 應用中使用 iOS App 擴充套件。
概述
#iOS App 擴充套件允許您在 iOS 應用之外擴充套件功能。您的應用可以作為主螢幕小元件出現,或者您可以讓應用的部分功能在其他應用內可用。
在以下示例中,當用戶選擇一張照片在 iOS 照片應用中分享時,名為 Example App With Extension 的 Flutter 應用會顯示在照片應用的分享表單中。
向 Flutter 應用新增 iOS App 擴充套件
#如果您想將 Flutter 應用與 iOS 作業系統整合,可以向 Flutter 專案新增 iOS App 擴充套件。為了實現流暢的工作流程,以下步驟展示瞭如何向名為 example_app_with_extension 的新 Flutter 應用新增 Share(分享) App 擴充套件,但您也可以從現有專案開始。
-
在控制檯中,建立一個名為
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的 App 擴充套件,並將其命名為ShareExtension。在 Xcode 選單欄中,選擇 File > New > Target。
新增 Share Extension。
在 Name 欄位中,輸入 ShareExtension。
點選 Finish(完成)。
在彈出的 Activate … Scheme 對話方塊中,選擇 Activate。
-
在 Xcode 中,更改構建過程的順序。
開啟 專案導航器 (View > Navigators > Project)。
在 專案導航器 頂部,選擇 Runner。
在主視窗的 TARGETS 下,選擇 Runner。
開啟 Build Phases 選項卡。
將 Embed Foundation Extensions 拖動到 Run Script 上方。
-
確保您的 Minimum Deployments (最低部署) iOS 版本設定正確,並且 Runner 和 ShareExtension 中的設定保持一致。
開啟 專案導航器 (View > Navigators > Project)。
在 專案導航器 頂部,選擇 Runner。
在主視窗的 TARGETS 下,選擇 Runner。
在 General 選項卡上,檢查您的 Minimum Deployments 下拉選單的值,使其與 ShareExtension > General 選項卡上的值相匹配。
-
在控制檯中,執行以下命令以重新構建您的 iOS 應用:
flutter build ios --config-only
當您新增新的 App 擴充套件時,Xcode 會根據您選擇的模板生成示例程式碼。有關生成程式碼和 WidgetKit 的更多資訊,請參閱 Apple 的 App 擴充套件文件。
測試 iOS App 擴充套件
#將 App 擴充套件新增到 Flutter 專案後,您可以使用模擬器或物理裝置進行測試。如果您在除錯模式下測試擴充套件,則必須使用 iOS 模擬器。
以下步驟假設您使用的是 新增 iOS App 擴充套件 中的示例應用程式和 Share 擴充套件。
在 Xcode 中,將 App 擴充套件新增到您的專案。
-
在控制檯中,使用以下命令執行您的 iOS 應用:
flutter run -
在模擬器中測試您的 App 擴充套件。
啟動支援 Share 擴充套件的應用,例如照片應用。
選擇一張照片,點選分享按鈕,然後點選您應用的分享擴充套件圖示。
將 App 擴充套件新增到您的專案。
-
在控制檯中,以釋出模式執行您的 Flutter 應用:
flutter run --release -
在您的裝置上測試您的 App 擴充套件。
啟動支援 Share 擴充套件的應用,例如照片應用。
選擇一張照片,點選分享按鈕,然後點選您應用的分享擴充套件圖示。
與 iOS App 擴充套件互動的其他方式
#Flutter 應用使用與 UIKit 或 SwiftUI 應用相同的技術與 iOS App 擴充套件進行互動。宿主應用和 App 擴充套件不會直接通訊。當裝置使用者與擴充套件互動時,宿主應用可能並未執行。應用和您的擴充套件可以讀取和寫入共享資源,或者使用更高階的 API 進行通訊。
使用更高階的 API
#有些擴充套件具有 API。例如,Core Spotlight 框架會對您的應用進行索引,允許使用者透過 Spotlight 和 Safari 進行搜尋。WidgetKit 框架可以觸發主螢幕小元件的更新。
為了簡化應用與擴充套件之間的通訊方式,Flutter 外掛封裝了這些 API。要查詢封裝了擴充套件 API 的外掛,請檢視 利用 Apple 的系統 API 和框架 或搜尋 pub.dev。
共享資源
#要共享 Flutter 應用和 App 擴充套件之間的資源,請將 Runner 應用目標和擴充套件目標放入同一個 App Group 中。
要將目標新增到 App Group:
在 Xcode 中開啟目標設定。
導航到 Signing & Capabilities 選項卡。
選擇 + Capability,然後選擇 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 外掛。
新增深度連結
#您可能希望引導使用者從 App 擴充套件跳轉到 Flutter 應用中的特定頁面。要開啟應用中的特定路由,您可以使用深度連結 (Deep Linking)。
新增可滾動列表
#預設情況下,Flutter 檢視不處理 Share 擴充套件中的滾動手勢。要在 Share 擴充套件中支援可滾動列表,請按照 GitHub 上的說明 進行操作。
在 iOS App 擴充套件中開啟 Flutter 應用
#您可以使用 FlutterViewController 直接在某些 iOS App 擴充套件(例如 Share 擴充套件)中開啟您的 Flutter 應用。
在以下示例中,名為 Example App With Extension 的 Flutter 應用在 Share 擴充套件中開啟,允許使用者在應用之間共享內容。
按照以下步驟在 Share App 擴充套件中顯示 Flutter 應用。在本示例中,App 擴充套件方案名為 ShareExtension,Flutter 應用方案名為 Runner,Flutter 應用名為 Example App With Extension。
-
如果您尚未執行,請向您的 Flutter 應用新增擴充套件。
-
在控制檯中,導航到您的 Flutter 專案目錄,然後使用以下命令在 Xcode 中開啟您的專案:
open ios/Runner.xcworkspace -
在 Xcode 中,停用使用者指令碼沙盒 (User Script Sandboxing)。
開啟 專案導航器 (View > Navigators > Project)。
在主視窗的 TARGETS 下,選擇 ShareExtension。
開啟 Build Settings 選項卡。
導航到 Build Options。
將 User Script Sandboxing 設定為 No。
-
在 Xcode 中,將預操作 (pre-action) 新增到
ShareExtension方案。開啟 Manage Schemes 視窗 (Product > Scheme > Manage Schemes)。
選擇 ShareExtension 方案並進行編輯。
展開 Build 選項卡。
選擇 Pre-actions。
點選 + 並選擇 New Run Script Action。
在 Provide build settings from 下拉列表中,選擇 ShareExtension。
在 Shell 文字欄位中,輸入:
/bin/sh "$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" prepare點選 Close。
-
在 Xcode 中,共享構建配置。
開啟 專案導航器 (View > Navigators > Project)。
在主視窗的 PROJECT 下,選擇 Runner。
開啟 Info 選項卡。
展開 Configuration。
展開 Debug 並更新 ShareExtension 的值,使其與 Runner 的值相匹配。
對 Profile 和 Release 重複上述步驟。
完成後,確保配置看起來與以下內容相似:

-
(可選)如果需要,在 Xcode 中將任何 Storyboard 檔案替換為擴充套件類。
開啟 專案導航器 (View > Navigators > Project)。
選擇 Runner > ShareExtension > Info。
展開 Information Property List。
刪除 NSExtensionMainStoryboard 鍵。
新增 NSExtensionPrincipalClass 鍵。
為
NSExtensionPrincipalClass鍵新增以下值之一:- (Swift) ShareExtension.ShareViewController
- (Objective-C) ShareViewController
-
在 Xcode 中,更新
ShareViewController以使用FlutterViewController。開啟 專案導航器 (View > Navigators > Project)。
選擇 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
註冊外掛
#按照以下步驟為 App 擴充套件註冊外掛。在本示例中,App 擴充套件方案名為 ShareExtension,Flutter 應用方案名為 Runner,Flutter 應用名為 Example App With Extension。
-
如果您尚未執行,請向您的 Flutter 應用新增擴充套件。
-
在 Xcode 中,將
GeneratedPluginRegistrant.m新增到 App 擴充套件目標。開啟 專案導航器 (View > Navigators > Project)。
在主視窗的 TARGETS 下,選擇 ShareExtension。
開啟 Build Phases 選項卡。
展開 Compile Sources。
點選 +。
在 Choose item to add 對話方塊的列表中,選擇 GeneratedPluginRegistrant.m。
點選 Add。
-
(僅 Swift)在 Xcode 中,更新
SWIFT_OBJC_BRIDGING_HEADER構建設定。開啟 專案導航器 (View > Navigators > Project)。
在主視窗的 TARGETS 下,選擇 ShareExtension。
開啟 Build Settings 選項卡。
選擇 All 過濾器。
導航到 Swift Compiler - General,並將 Objective-C Bridging Header 鍵的值更改為 Runner/Runner-Bridging-Header.h。
-
在 Xcode 中,更新
ShareViewController的程式碼以註冊GeneratedPluginRegistrant.h。開啟 專案導航器 (View > Navigators > Project)。
選擇 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 時,它不支援在物理裝置上以除錯模式完全執行 App 擴充套件,因為物理裝置可能會耗盡記憶體。
-
iOS App 擴充套件的記憶體有限。建議僅在 App 擴充套件支援至少 100MB 記憶體的情況下修改其 UI。
在 iOS App 擴充套件中呼叫 Dart 程式碼 / 渲染 Flutter 內容
#home_widget 軟體包提供了大量功能,包括允許執行以下操作:
其他資源
#有關在 Flutter iOS 應用中使用 App 擴充套件的分步說明,請檢視 向您的 Flutter 應用新增主螢幕小元件 Codelab。
要了解有關向 iOS 應用新增 Flutter 螢幕的各種方式的更多資訊,請參閱 向 iOS 應用新增 Flutter 螢幕。