添加 iOS App Clip 目标
本指南介绍如何手动为现有的 Flutter 项目或 add-to-app 项目添加另一个 Flutter 渲染的 iOS App Clip 目标。
要查看可运行的示例,请参阅 GitHub 上的 App Clip 示例。
步骤 1 - 打开项目
#打开您的 iOS Xcode 项目,例如完整 Flutter 应用的 ios/Runner.xcworkspace
。
步骤 2 - 添加 App Clip 目标
#2.1
在项目导航器中点击您的项目,以显示项目设置。
点击目标列表底部的 + 以添加新目标。

2.2
为您的新目标选择 **App Clip** 类型。

2.3
在对话框中输入您的新目标详细信息。
选择 **Storyboard** 作为界面。
为 **Language** 选择与您的原始目标相同的语言。
(换句话说,为了简化设置,请不要为 Objective-C 主目标创建 Swift App Clip 目标,反之亦然。)

2.4
在接下来的对话框中,激活新目标的新方案。

2.5
回到项目设置,打开 **Build Phases**(构建阶段)选项卡。将 **Embedded App Clips** 拖到 **Thin Binary**(精简二进制文件)的上方。

步骤 3 - 删除不需要的文件
#3.1
在项目导航器中,在刚创建的 App Clip 组中,删除 Info.plist
和 <app clip target>.entitlements
之外的所有内容。

将文件移至废纸篓。
3.2
如果您不使用 SceneDelegate.swift
文件,请从 Info.plist
中删除对其的引用。
打开 App Clip 组中的 Info.plist
文件。删除 **Application Scene Manifest**(应用程序场景清单)的整个字典条目。

步骤 4 - 共享构建配置
#对于 add-to-app 项目,此步骤不是必需的,因为 add-to-app 项目拥有自定义的构建配置和版本。
4.1
回到项目设置,选择项目条目,而不是任何目标。
在 **Info**(信息)选项卡下,展开 **Configurations**(配置)可展开组,然后展开 **Debug**(调试)、**Profile**(配置文件)和 **Release**(发布)条目。
对于每一个,从下拉菜单中为 App Clip 目标选择与正常应用目标条目相同的选项。
这样,您的 App Clip 目标就可以访问 Flutter 所需的构建设置。
将 **iOS Deployment Target**(iOS 部署目标)设置为至少 **16.0**,以利用 15MB 的大小限制。

4.2
在 App Clip 组的 Info.plist
文件中,设置
Build version string (short)
(构建版本字符串(短))为$(FLUTTER_BUILD_NAME)
Bundle version
(捆绑包版本)为$(FLUTTER_BUILD_NUMBER)
步骤 5 - 共享代码和资源
#选项 1 - 共享所有内容
#假设目标是在 App Clip 中显示与标准应用相同的 Flutter UI,请共享相同的代码和资源。
对于以下每个文件:Main.storyboard
、Assets.xcassets
、LaunchScreen.storyboard
、GeneratedPluginRegistrant.m
以及 AppDelegate.swift
(如果使用 Objective-C,则还包括 Supporting Files/main.m
),选择文件,然后在检查器的第一个选项卡中,在 Target Membership
(目标成员资格)复选框组中也包含 App Clip 目标。

选项 2 - 自定义 App Clip 的 Flutter 启动
#在这种情况下,请勿删除 步骤 3 中列出的所有内容。而是使用脚手架和 iOS add-to-app API 从此代码执行自定义 Flutter 启动。例如,显示 自定义 Flutter 路由。
步骤 6 - 添加 App Clip 关联域
#这是 App Clip 开发的标准步骤。请参阅 Apple 官方文档。
6.1
打开 <app clip target>.entitlements
文件。添加一个 **Associated Domains**(关联域)数组类型。向数组添加一行,值为 appclips:<your bundle id>
。

6.2
同样,需要在您的主应用中添加相同的关联域权限。
将 <app clip target>.entitlements
文件从您的 App Clip 组复制到您的主应用组,并将其重命名为主目标相同的名称,例如 Runner.entitlements
。
打开文件,删除主应用的权限文件中的 Parent Application Identifiers
(父应用程序标识符)条目(为 App Clip 的权限文件保留该条目)。

6.3
回到项目设置,选择主应用的 **Build Settings**(构建设置)选项卡。将 **Code Signing Entitlements**(代码签名权限)设置为主应用创建的第二个权限文件的相对路径。

步骤 7 - 集成 Flutter
#对于 add-to-app,这些步骤不是必需的。
7.1
对于 Swift 目标,将 Objective-C Bridging Header
(Objective-C 桥接头文件)构建设置设置为 Runner/Runner-Bridging-Header.h
换句话说,与主应用目标设置相同。

7.2
现在打开 **Build Phases**(构建阶段)选项卡。点击 **+** 号,选择 **New Run Script Phase**(新建运行脚本阶段)。

将此新阶段拖到 **Dependencies**(依赖项)阶段下方。
展开新阶段,并在脚本内容中添加以下行:
/bin/sh "$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" build
取消选中 **Based on dependency analysis**(基于依赖分析)。
换句话说,与主应用目标的构建阶段相同。

这确保了在运行 App Clip 目标时,您的 Flutter Dart 代码会被编译。
7.3
再次点击 **+** 号,选择 **New Run Script Phase**(新建运行脚本阶段)。将其保留为最后一个阶段。
这次,添加:
/bin/sh "$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" embed_and_thin
取消选中 **Based on dependency analysis**(基于依赖分析)。
换句话说,与主应用目标的构建阶段相同。

这确保了您的 Flutter 应用和引擎会被嵌入到 App Clip 包中。
步骤 8 - 集成插件
#8.1
打开您的 Flutter 项目或 add-to-app 主项目的 Podfile
。
对于完整 Flutter 应用,请替换以下部分:
target 'Runner' do
use_frameworks!
use_modular_headers!
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
end
为:
use_frameworks!
use_modular_headers!
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
target 'Runner'
target '<name of your App Clip target>'
在文件顶部,还要取消注释 platform :ios, '13.0'
并将版本设置为两个目标中较低的 iOS 部署目标。
对于 add-to-app,请添加到:
target 'MyApp' do
install_all_flutter_pods(flutter_application_path)
end
为:
target 'MyApp' do
install_all_flutter_pods(flutter_application_path)
end
target '<name of your App Clip target>'
install_all_flutter_pods(flutter_application_path)
end
8.2
从命令行进入您的 Flutter 项目目录,然后安装 pod。
cd ios
pod install
运行
#现在,您可以通过 Xcode 运行您的 App Clip 目标,方法是:从方案下拉菜单中选择您的 App Clip 目标,选择 iOS 16 或更高版本的设备,然后按运行。

要测试从头开始启动 App Clip,请参考 Apple 关于 测试 App Clip 启动体验 的文档。
调试,热重载
#不幸的是,由于网络权限限制,flutter attach
无法自动发现 App Clip 中的 Flutter 会话。
然后,您必须将其复制并粘贴回 flutter attach
命令以进行连接。
例如
flutter attach --debug-uri <copied URI>