添加 iOS 应用扩展
本指南向你展示如何在 Flutter 应用中使用 iOS 应用扩展。
概述
#iOS 应用扩展允许你扩展 iOS 应用之外的功能。你的应用可以显示为主屏幕小组件,或者你可以将应用的部分功能提供给其他应用使用。
在以下示例中,当用户在 iOS 照片应用中选择要分享的照片时,一个名为 Example App With Extension
的 Flutter 应用会显示在照片应用的分享表中。

将 iOS 应用扩展添加到你的 Flutter 应用
#如果你想将 Flutter 应用与 iOS 操作系统集成,可以将 iOS 应用扩展添加到你的 Flutter 项目中。为了实现无缝的工作流程,以下步骤展示了如何将 共享 (Share) 应用扩展添加到名为 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 菜单栏中,选择 File > New > Target。
添加 Share Extension。
在 Name field(名称字段)中,输入 ShareExtension。
点击 Finish(完成)。
在弹出的 Activate … Scheme(激活…方案)对话框中,选择 Activate(激活)。
在 Xcode 中,更改构建过程的顺序。
打开 project navigator(项目导航器)(View > Navigators > Project)。
在 project navigator(项目导航器)顶部,选择 Runner。
在主窗口的 TARGETS(目标)下,选择 Runner。
打开 Build Phases(构建阶段)选项卡。
将 Embed Foundation Extensions 拖到 Run Script 上方。
在控制台中,运行以下命令以重新构建你的 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) 中。
将目标添加到应用组
在 Xcode 中打开目标设置。
导航到 Signing & Capabilities(签名与功能)选项卡。
选择 + Capability(+ 功能)然后选择 App Groups(应用组)。
从以下两个选项中选择要将目标添加到的应用组
- 从列表中选择一个应用组。
- 点击 + 添加新的应用组。

当两个目标属于同一个应用组时,它们可以读写同一个源。为你的数据选择以下源之一。
- 键/值: 使用
shared_preference_app_group
插件在同一个应用组内读写UserDefaults
。 - 文件: 使用
path_provider
插件获取的应用组容器路径来读写文件。 - 数据库: 使用
path_provider
插件获取的应用组容器路径,并通过sqflite
插件创建数据库。
安排后台更新
#后台任务提供了一种通过代码更新扩展的方式,无论你的应用状态如何。
要从 Flutter 应用调度后台工作,请使用 workmanager
插件。
添加深度链接
#你可能希望将用户从应用扩展引导到 Flutter 应用中的特定页面。要在应用中打开特定路由,你可以使用深度链接 (Deep Linking)。
添加可滚动列表
#默认情况下,Flutter 视图在共享 (Share) 扩展中不处理滚动手势。要在共享扩展中支持可滚动列表,请遵循这些说明。
在 iOS 应用扩展中打开 Flutter 应用
#你可以使用 FlutterViewController
直接在某些 iOS 应用扩展(例如共享 (Share) 扩展)中打开你的 Flutter 应用。
在以下示例中,一个名为 Example App With Extension
的 Flutter 应用在共享扩展中打开,该扩展允许用户在应用之间共享内容。

使用以下步骤在共享 (Share) 应用扩展中显示 Flutter 应用。在此示例中,应用扩展方案名为 ShareExtension
,Flutter 应用方案名为 Runner
,Flutter 应用名为 Example App With Extension
。
如果尚未这样做,请将扩展添加到你的 Flutter 应用。
在控制台中,导航到你的 Flutter 项目目录,然后使用以下命令在 Xcode 中打开你的项目
open ios/Runner.xcworkspace
在 Xcode 中,禁用用户脚本沙盒。
打开 project navigator(项目导航器)(View > Navigators > Project)。
在主窗口的 TARGETS(目标)下,选择 ShareExtension。
打开 Build Settings(构建设置)选项卡。
导航到 Build Options(构建选项)。
将 User Script Sandboxing(用户脚本沙盒)设置为 No(否)。
在 Xcode 中,将预操作添加到
ShareExtension
方案。打开 Manage Schemes(管理方案)窗口(Product > Scheme > Manage Schemes)。
选择 ShareExtension 方案并编辑它。
展开 Build(构建)选项卡。
选择 Pre-actions(预操作)。
点击 + 并选择 New Run Script Action(新建运行脚本操作)。
在 Provide build settings from(提供构建设置来自)下拉列表中,选择 ShareExtension。
在 Shell(Shell 脚本)文本字段中,输入
/bin/sh "$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" prepare
点击 Close(关闭)。
在 Xcode 中,共享构建配置。
打开 project navigator(项目导航器)(View > Navigators > Project)。
在主窗口的 PROJECT(项目)下,选择 Runner。
打开 Info(信息)选项卡。
展开 Configuration(配置)。
展开 Debug(调试)并更新 ShareExtension 的值以匹配 Runner 的值。
对 Profile(配置文件)和 Release(发布)重复上一步。
完成后,确保配置类似于以下内容
(可选) 在 Xcode 中,如果需要,用扩展类替换任何故事板文件。
打开 project navigator(项目导航器)(View > Navigators > Project)。
选择 Runner > ShareExtension > Info。
展开 Information Property List(信息属性列表)。
删除 NSExtensionMainStoryboard 键。
添加 NSExtensionPrincipalClass 键。
为
NSExtensionPrincipalClass
键添加以下值之一- (Swift) ShareExtension.ShareViewController
- (Objective-C) ShareViewController
在 Xcode 中,更新
ShareViewController
以使用FlutterViewController
。打开 project navigator(项目导航器)(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
注册插件
#使用以下步骤为应用扩展注册插件。在此示例中,应用扩展方案名为 ShareExtension
,Flutter 应用方案名为 Runner
,Flutter 应用名为 Example App With Extension
。
如果尚未这样做,请将扩展添加到你的 Flutter 应用。
在 Xcode 中,将
GeneratedPluginRegistrant.m
添加到应用扩展目标。打开 project navigator(项目导航器)(View > Navigators > Project)。
在主窗口的 TARGETS(目标)下,选择 ShareExtension。
打开 Build Phases(构建阶段)选项卡。
展开 Compile Sources(编译源)。
点击 +。
从 Choose item to add(选择要添加的项)对话框的列表中,选择 GeneratedPluginRegistrant.m。
点击 Add(添加)。
(仅限 Swift) 在 Xcode 中,更新
SWIFT_OBJC_BRIDGING_HEADER
构建设置。打开 project navigator(项目导航器)(View > Navigators > Project)。
在主窗口的 TARGETS(目标)下,选择 ShareExtension。
打开 Build Settings(构建设置)选项卡。
选择 All(全部)过滤器。
导航到 Swift Compiler - General(Swift 编译器 - 通用)并更改 Objective-C Bridging Header(Objective-C 桥接头)键的值为 Runner/Runner-Bridging-Header.h。
在 Xcode 中,更新
ShareViewController
的代码以注册GeneratedPluginRegistrant.h
。打开 project navigator(项目导航器)(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 时),因为物理设备可能会耗尽内存。
iOS 应用扩展的内存有限。建议仅当应用扩展支持至少 100MB 内存时才修改其 UI。
其他资源
#有关如何在 Flutter iOS 应用中使用应用扩展的逐步说明,请查看 将主屏幕小组件添加到 Flutter 应用 的 Codelab。
要了解有关将 Flutter 屏幕添加到 iOS 应用的各种方法,请参阅将 Flutter 屏幕添加到 iOS 应用。