跳到主內容

新增 iOS App 擴充套件

瞭解如何向 Flutter 應用新增 App 擴充套件

本指南向您展示如何在 Flutter 應用中使用 iOS App 擴充套件。

概述

#

iOS App 擴充套件允許您在 iOS 應用之外擴充套件功能。您的應用可以作為主螢幕小元件出現,或者您可以讓應用的部分功能在其他應用內可用。

在以下示例中,當用戶選擇一張照片在 iOS 照片應用中分享時,名為 Example App With Extension 的 Flutter 應用會顯示在照片應用的分享表單中。

Share sheet with a Flutter app in it.

向 Flutter 應用新增 iOS App 擴充套件

#

如果您想將 Flutter 應用與 iOS 作業系統整合,可以向 Flutter 專案新增 iOS App 擴充套件。為了實現流暢的工作流程,以下步驟展示瞭如何向名為 example_app_with_extension 的新 Flutter 應用新增 Share(分享) App 擴充套件,但您也可以從現有專案開始。

  1. 在控制檯中,建立一個名為 example_app_with_extension 的新 Flutter 專案。

    flutter create example_app_with_extension
    
  2. 在控制檯中,開啟 example_app_with_extension 專案的 Xcode 工作區。

    cd example_app_with_extension && open ios/Runner.xcworkspace
    
  3. 在 Xcode 中,新增一個名為 Share 的 App 擴充套件,並將其命名為 ShareExtension

    • 在 Xcode 選單欄中,選擇 File > New > Target

    • 新增 Share Extension

    • Name 欄位中,輸入 ShareExtension

    • 點選 Finish(完成)。

    • 在彈出的 Activate … Scheme 對話方塊中,選擇 Activate

  4. 在 Xcode 中,更改構建過程的順序。

    • 開啟 專案導航器 (View > Navigators > Project)。

    • 專案導航器 頂部,選擇 Runner

    • 在主視窗的 TARGETS 下,選擇 Runner

    • 開啟 Build Phases 選項卡。

    • Embed Foundation Extensions 拖動到 Run Script 上方。

  5. 確保您的 Minimum Deployments (最低部署) iOS 版本設定正確,並且 RunnerShareExtension 中的設定保持一致。

    • 開啟 專案導航器 (View > Navigators > Project)。

    • 專案導航器 頂部,選擇 Runner

    • 在主視窗的 TARGETS 下,選擇 Runner

    • General 選項卡上,檢查您的 Minimum Deployments 下拉選單的值,使其與 ShareExtension > General 選項卡上的值相匹配。

  6. 在控制檯中,執行以下命令以重新構建您的 iOS 應用:

    flutter build ios --config-only
    
  7. 在模擬器中測試您的應用.

當您新增新的 App 擴充套件時,Xcode 會根據您選擇的模板生成示例程式碼。有關生成程式碼和 WidgetKit 的更多資訊,請參閱 Apple 的 App 擴充套件文件

測試 iOS App 擴充套件

#

將 App 擴充套件新增到 Flutter 專案後,您可以使用模擬器或物理裝置進行測試。如果您在除錯模式下測試擴充套件,則必須使用 iOS 模擬器。

以下步驟假設您使用的是 新增 iOS App 擴充套件 中的示例應用程式和 Share 擴充套件。

  1. 在 Xcode 中,將 App 擴充套件新增到您的專案

  2. 在控制檯中,使用以下命令執行您的 iOS 應用:

    flutter run
    
  3. 在模擬器中測試您的 App 擴充套件。

    • 啟動支援 Share 擴充套件的應用,例如照片應用。

    • 選擇一張照片,點選分享按鈕,然後點選您應用的分享擴充套件圖示。

  1. 將 App 擴充套件新增到您的專案。

  2. 在控制檯中,以釋出模式執行您的 Flutter 應用:

    flutter run --release
    
  3. 在您的裝置上測試您的 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:

  1. 在 Xcode 中開啟目標設定。

  2. 導航到 Signing & Capabilities 選項卡。

  3. 選擇 + Capability,然後選擇 App Groups

  4. 從兩個選項中選擇要將目標新增到的 App Group:

    1. 從列表中選擇一個 App Group。
    2. 點選 + 以新增新的 App Group。
Selecting an App Group within an Xcode Runner target configuration.

當兩個目標屬於同一個 App Group 時,它們可以讀取和寫入同一個源。為您的資料選擇以下源之一:

安排後臺更新

#

後臺任務提供了一種無論應用狀態如何,都能透過程式碼更新擴充套件的方法。

要從 Flutter 應用安排後臺工作,請使用 workmanager 外掛。

新增深度連結

#

您可能希望引導使用者從 App 擴充套件跳轉到 Flutter 應用中的特定頁面。要開啟應用中的特定路由,您可以使用深度連結 (Deep Linking)

新增可滾動列表

#

預設情況下,Flutter 檢視不處理 Share 擴充套件中的滾動手勢。要在 Share 擴充套件中支援可滾動列表,請按照 GitHub 上的說明 進行操作。

在 iOS App 擴充套件中開啟 Flutter 應用

#

您可以使用 FlutterViewController 直接在某些 iOS App 擴充套件(例如 Share 擴充套件)中開啟您的 Flutter 應用。

在以下示例中,名為 Example App With Extension 的 Flutter 應用在 Share 擴充套件中開啟,允許使用者在應用之間共享內容。

An example of an entry added to the share menu by a Flutter app

按照以下步驟在 Share App 擴充套件中顯示 Flutter 應用。在本示例中,App 擴充套件方案名為 ShareExtension,Flutter 應用方案名為 Runner,Flutter 應用名為 Example App With Extension

  1. 如果您尚未執行,請向您的 Flutter 應用新增擴充套件

  2. 在控制檯中,導航到您的 Flutter 專案目錄,然後使用以下命令在 Xcode 中開啟您的專案:

    open ios/Runner.xcworkspace
    
  3. 在 Xcode 中,停用使用者指令碼沙盒 (User Script Sandboxing)。

    • 開啟 專案導航器 (View > Navigators > Project)。

    • 在主視窗的 TARGETS 下,選擇 ShareExtension

    • 開啟 Build Settings 選項卡。

    • 導航到 Build Options

    • User Script Sandboxing 設定為 No

  4. 在 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

  5. 在 Xcode 中,共享構建配置。

    • 開啟 專案導航器 (View > Navigators > Project)。

    • 在主視窗的 PROJECT 下,選擇 Runner

    • 開啟 Info 選項卡。

    • 展開 Configuration

    • 展開 Debug 並更新 ShareExtension 的值,使其與 Runner 的值相匹配。

    • ProfileRelease 重複上述步驟。

    • 完成後,確保配置看起來與以下內容相似:

      Xcode configurations

  6. (可選)如果需要,在 Xcode 中將任何 Storyboard 檔案替換為擴充套件類。

    • 開啟 專案導航器 (View > Navigators > Project)。

    • 選擇 Runner > ShareExtension > Info

    • 展開 Information Property List

    • 刪除 NSExtensionMainStoryboard 鍵。

    • 新增 NSExtensionPrincipalClass 鍵。

    • NSExtensionPrincipalClass 鍵新增以下值之一:

      • (Swift) ShareExtension.ShareViewController
      • (Objective-C) ShareViewController
  7. 在 Xcode 中,更新 ShareViewController 以使用 FlutterViewController

    • 開啟 專案導航器 (View > Navigators > Project)。

    • 選擇 Runner > ShareExtension > ShareViewController

    • 更新 ShareViewController 以使用 FlutterViewController 類:

ShareViewController.swift
swift
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))
    }
}
ShareViewController.h
objc
@import Flutter;
@import UIKit;

@interface ShareViewController : UIViewController

@end
ShareViewController.m
objc
#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
  1. 在模擬器中測試您的應用.

註冊外掛

#

按照以下步驟為 App 擴充套件註冊外掛。在本示例中,App 擴充套件方案名為 ShareExtension,Flutter 應用方案名為 Runner,Flutter 應用名為 Example App With Extension

  1. 如果您尚未執行,請向您的 Flutter 應用新增擴充套件

  2. 在 Xcode 中,將 GeneratedPluginRegistrant.m 新增到 App 擴充套件目標。

    • 開啟 專案導航器 (View > Navigators > Project)。

    • 在主視窗的 TARGETS 下,選擇 ShareExtension

    • 開啟 Build Phases 選項卡。

    • 展開 Compile Sources

    • 點選 +

    • Choose item to add 對話方塊的列表中,選擇 GeneratedPluginRegistrant.m

    • 點選 Add

  3. (僅 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

  4. 在 Xcode 中,更新 ShareViewController 的程式碼以註冊 GeneratedPluginRegistrant.h

    • 開啟 專案導航器 (View > Navigators > Project)。

    • 選擇 Runner > ShareExtension > ShareViewController

    • 更新 ShareViewController 檔案以使用 GeneratedPluginRegistrant.h

ShareViewController.swift
swift
// Add this inside `showFlutter()` at the top
GeneratedPluginRegistrant.register(with: flutterEngine)
ShareViewController.m
objc
// Add this import at the top
#import "GeneratedPluginRegistrant.h"
ShareViewController.m
objc
// Add this after [flutterEngine run]
[GeneratedPluginRegistrant registerWithRegistry:flutterEngine];
  1. (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 螢幕