添加 iOS App Clip target

这个指南介绍了如何手动添加另一个使用 Flutter 来渲染的 iOS App Clip target, 并将它集成到您现有的 Flutter 项目或 add-to-app 项目。

要查看完整可用的示例,请参阅 GitHub 上的 App Clip 示例

步骤 1 - 打开项目

打开您的 iOS Xcode 工程,例如您的纯 Flutter 项目中的 ios/Runner.xcworkspace

步骤 2 - 添加一个 App Clip 的 target

2.1

点击您项目的 Project Navigator 来显示工程设置。

点击 target 列表底部的 + 来添加一个新的 target。

2.2

为您的新 target 选择 App Clip 类型。

2.3

在对话框为您的新 target 输入详情。

选择 Storyboard 作为界面。

选择 UIKit App Delegate 作为生命周期。

选择与您原来的 target 相同的编程语言

(换句话说,请勿为 Objective-C target 创建 Swift 类型的 App Clip target,反之亦然,以简化设置。)

2.4

在接下来的对话框中,为新的 target 激活 (activate) 一个新的 scheme。

步骤 3 - 移除不需要的文件

3.1

在项目 Project Navigator 的新创建的 App Clip 组中,将除了 Info.plistApp 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

返回项目设置,现在选择 Project 条目,而不是 Targets 里的任何 target。

Info 选项卡页中的 Configurations 可扩展组下,展开 DebugProfileRelease 条目。

每一个 App Clip target 的下拉菜单的值都应该与常规应用 target 中的值相同。

这使您的 App Clip target 可以访问 Flutter 的必需构建设置。

4.2

在 App Clip 组的 Info.plist 文件中,设置:

  • Build version string (short) to $(FLUTTER_BUILD_NAME)
  • Bundle version to $(FLUTTER_BUILD_NUMBER)

步骤 5 - 共享代码和资源

选项 1 - 共享所有东西

假设您的目标是在 App Clip 中显示与普通应用相同的 Flutter UI,并共享相同的代码和资源。

对于以下每一个文件: Main.storyboardAssets.xcassetsLaunchScreen.storyboardGeneratedPluginRegistrant.mAppDelegate.swift,(如果您是 Objective-C 还应该包括 Supporting Files/main.m)选择文件并且在检查器中选择第一个选项卡,并且在 Target Membership 选中 App Clip

选项 2 - 为 App Clip 自定义 Flutter 的启动器

在这个例子中,不需要删除在 步骤 3 中的任何东西。相对的,使用 iOS add-to-app APIs 的模板来自定义 Flutter 启动器。可以参考示例 自定义 Flutter 路由

步骤 6 - 添加 App Clip 的关联域名

这是一个 App Clip 开发的标准步骤。请查看 苹果官方文档

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

返回项目设置,选择主应用 target,打开 Build Settings 选项卡。设置 Code Signing Entitlements 的值为主应用创建的第二个授权文件的相对路径。

步骤 7 - 整合 Flutter

add-to-app 不需要这些步骤。

7.1

在您的 App Clip 的 target 的项目设置,打开 Build Settings 选项卡。

Framework Search Paths 添加两个内容:

  • $(inherited)
  • $(PROJECT_DIR)/Flutter

换句话说,与主应用程序 target 的构建设置相同。

7.2

如果是 Swift target,设置 Objective-C Bridging Header 构建配置为 Runner/Runner-Bridging-Header.h

换句话说,与主应用程序 target 的构建设置相同。

7.3

现在打开 Build Phases 选项卡。点击 + 并且选择 New Run Script Phase

拖动新的 phase 到 Dependencies phase。

展开新 phase 并将以下内容添加到脚本:

/bin/sh "$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" build

简单来说,与主应用程序 target 的构建设置相同。

这可以确保在运行 App Clip target 时编译 Flutter 的 Dart 代码。

7.4

再次点击 + 并且选择 New Run Script Phase。这是最后一个 phase。

这次添加如下内容:

/bin/sh "$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" embed_and_thin

简单来说,与主应用程序 target 的构建设置相同。

这将确保您的 Flutter 应用程序和引擎嵌入到 App Clip bundle 中。

Step 8 - Disable Bitcode

在 App Clip target 的 Build Settings 选项卡中,将 Enable Bitcode 设置设置为 No。

Step 9 - 整合插件

9.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, '9.0' 的注释解除,并且为您的 2 个 target 设置最低可运行的 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

9.2

在命令行中,目前工作目录需要是您的 Flutter 项目目录,然后安装 pod:

cd ios
pod install

运行

您现在可以在 Xcode 的 scheme 下拉中选择并运行您的 App Clip target 了,选择一个 iOS 14 的设备并点击运行。

要从头测试 App Clip 的启动,您也可以查看苹果公司的文档 测试您的 App Clip 的启动体验

调试和热重载

不幸的是,由于网络权限的原因,flutter attach 无法在 App clip 中自动发现 Flutter 会话。

为了调试 App clip 并使用诸如热重新加载之类的功能,必须在运行应用后从 Xcode 中的控制台输出中查找 Observatory URI。

您需要复制粘贴它们到 flutter attach 来连接。

例如:

flutter attach --debug-uri <copied URI>