添加 iOS 应用扩展
了解如何将应用扩展添加到你的 Flutter 应用
本指南演示了如何在 Flutter 应用中使用 iOS 应用扩展。
概述
#iOS 应用扩展 允许你在 iOS 应用之外扩展功能。 你的应用可以显示为主屏幕小部件,或者你可以在其他应用中提供应用的部分功能。
在以下示例中,当用户在 iOS 照片应用中选择要共享的照片时,名为 Example App With Extension 的 Flutter 应用会显示在照片应用共享表中
将 iOS 应用扩展添加到你的 Flutter 应用
#如果你想将你的 Flutter 应用与 iOS 操作系统集成,可以将 iOS 应用扩展添加到你的 Flutter 项目中。 为了获得流畅的工作流程,以下步骤演示了如何将 共享 应用扩展添加到名为 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。
在主窗口的 目标 下方,选择 Runner。
打开 构建阶段 选项卡。
将 嵌入 Foundation 扩展 拖动到 运行脚本 之上。
-
确保你的 最低部署 iOS 值设置正确,并且在 Runner 和 ShareExtension 中匹配
打开 项目导航器 (视图 > 导航器 > 项目)。
在 项目导航器 中,顶部选择 Runner。
在主窗口的 目标 下方,选择 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 应用使用与 UIKit 或 SwiftUI 应用相同的方法与 iOS 应用扩展进行交互。 包含的应用和应用扩展不直接通信。 包含的应用可能在设备用户与扩展交互时未运行。 该应用和你的扩展可以读取和写入共享资源,或使用更高级别的 API 进行通信。
使用更高级别的 API
#某些扩展具有 API。 例如,Core Spotlight 框架会索引你的应用,允许用户从 Spotlight 和 Safari 中搜索。 WidgetKit 框架可以触发主屏幕小部件的更新。
为了简化你的应用与扩展之间的通信,Flutter 插件封装了这些 API。 要查找封装扩展 API 的插件,请查看 利用 Apple 的系统 API 和框架 或搜索 pub.dev。
共享资源
#要共享你的 Flutter 应用和应用扩展之间的资源,请将 Runner 应用目标和扩展目标放在同一个 应用组 中。
要将目标添加到应用组
打开 Xcode 中的目标设置。
导航到 签名与功能 选项卡。
选择 + 功能 然后 应用组。
-
从两个选项中选择要添加目标的应用程序组
- 从列表中选择一个应用组。
- 点击 + 添加一个新的应用组。
当两个目标属于同一个应用组时,它们可以读取和写入相同的源。 为你的数据选择以下其中一种源。
-
键/值: 使用
shared_preference_app_group插件在同一个应用组中读取或写入UserDefaults。 -
文件: 使用
path_provider插件中的应用组容器路径来 读取和写入文件。 -
数据库: 使用
path_provider插件中的应用组容器路径来使用sqflite插件创建数据库。
安排后台更新
#后台任务提供了一种无论你的应用状态如何,都可以通过代码更新你的扩展的方式。
要从你的 Flutter 应用安排后台工作,请使用 workmanager 插件。
添加深度链接
#你可能希望将用户从应用扩展定向到你的 Flutter 应用中的特定页面。 要打开应用中的特定路由,可以使用 深度链接。
添加可滚动列表
#默认情况下,flutter 视图无法处理 共享 扩展中的滚动手势。 要支持共享扩展中的可滚动列表,请遵循 GitHub 上的说明。
在 iOS 应用扩展中打开 Flutter 应用
#你可以使用 FlutterViewController 在某些 iOS 应用扩展(例如 共享 扩展)中直接在你的 Flutter 应用中打开你的 Flutter 应用。
在以下示例中,名为 Example App With Extension 的 Flutter 应用在共享扩展中打开,允许用户在应用之间共享内容
使用以下步骤在 共享 应用扩展中显示 Flutter 应用。 在此示例中,应用扩展方案称为 ShareExtension,Flutter 应用方案称为 Runner,Flutter 应用称为 Example App With Extension
-
将扩展添加到你的 Flutter 应用(如果尚未这样做)。
-
在控制台中,导航到你的 Flutter 项目目录,然后使用以下命令在 Xcode 中打开你的项目
open ios/Runner.xcworkspace -
在 Xcode 中,禁用用户脚本沙盒。
打开 项目导航器 (视图 > 导航器 > 项目)。
在主窗口的 目标 下方,选择 ShareExtension。
打开 构建设置 选项卡。
导航到 构建选项。
将 用户脚本沙盒 设置为 否。
-
在 Xcode 中,将预操作添加到
ShareExtension方案。打开 管理方案 窗口 (产品 > 方案 > 管理方案)。
选择 ShareExtension 方案并进行编辑。
展开 构建 选项卡。
选择 预操作。
点击 + 并选择 新建运行脚本操作。
在 从以下构建设置提供 下拉列表中,选择 ShareExtension。
在 Shell 文本字段中,输入
/bin/sh "$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" prepare点击 关闭。
-
在 Xcode 中,共享构建配置。
打开 项目导航器 (视图 > 导航器 > 项目)。
在主窗口的 项目 下方,选择 Runner。
打开 信息 选项卡。
展开 配置。
展开 调试 并更新 ShareExtension 的值以匹配 Runner 的值。
对 Profile 和 Release 重复上一步。
完成操作后,请确保配置如下所示

-
(可选)在 Xcode 中,如果需要,用扩展类替换任何故事板文件。
打开 项目导航器 (视图 > 导航器 > 项目)。
选择 Runner > ShareExtension > 信息。
展开 信息属性列表。
删除 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添加到应用扩展目标。打开 项目导航器 (视图 > 导航器 > 项目)。
在主窗口的 目标 下方,选择 ShareExtension。
打开 构建阶段 选项卡。
展开 编译源代码。
点击 +。
在选择要添加的项目对话框的列表中,选择 GeneratedPluginRegistrant.m。
点击 添加。
-
(Swift only) 在 Xcode 中,更新
SWIFT_OBJC_BRIDGING_HEADER构建设置。打开 项目导航器 (视图 > 导航器 > 项目)。
在主窗口的 目标 下方,选择 ShareExtension。
打开 构建设置 选项卡。
选择 全部 过滤器。
导航到 Swift 编译器 - 通用,并将 Objective-C Bridging Header 键的值更改为 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 应用 代码实验室。
要了解有关将 Flutter 屏幕添加到 iOS 应用的各种方法,请参阅 将 Flutter 屏幕添加到 iOS 应用。