将 Flutter 模块集成到您的 iOS 项目中
Flutter UI 组件可以作为嵌入式框架逐步添加到您现有的 iOS 应用程序中。要将 Flutter 嵌入到现有应用程序中,请考虑以下三种方法之一。
嵌入方法 | 方法 | 优点 |
---|---|---|
使用 CocoaPods(推荐) | 安装并使用 Flutter SDK 和 CocoaPods。每次 Xcode 构建 iOS 应用时,Flutter 都会从源代码编译 flutter_module 。 | 将 Flutter 嵌入到您的应用中最简单的方法。 |
使用 iOS 框架 | 为 Flutter 组件创建 iOS 框架,将它们嵌入到您的 iOS 中,并更新现有应用的构建设置。 | 不需要每个开发人员都在本地机器上安装 Flutter SDK 和 CocoaPods。 |
使用 iOS 框架和 CocoaPods | 在 Xcode 中嵌入 iOS 应用和插件的框架,但将 Flutter 引擎作为 CocoaPods podspec 分发。 | 提供了分发大型 Flutter 引擎 (Flutter.xcframework ) 库的替代方法。 |
将 Flutter 添加到现有 iOS 应用时,会增加 iOS 应用的大小。
有关使用用 UIKit 构建的应用的示例,请参阅添加到应用代码示例 中的 iOS 目录。有关使用 SwiftUI 的示例,请参阅新闻资讯应用中的 iOS 目录。
开发系统要求
#您的开发环境必须满足Flutter 的 macOS 系统要求([macOS system requirements for Flutter]),并安装 Xcode([Xcode installed])。Flutter 支持 Xcode 15 或更高版本和CocoaPods 1.16 或更高版本。
创建 Flutter 模块
#要使用任何方法将 Flutter 嵌入到现有应用程序中,首先请创建一个 Flutter 模块。使用以下命令创建 Flutter 模块。
cd /path/to/my_flutter
flutter create --template module my_flutter
Flutter 在 /path/to/my_flutter/
下创建模块项目。如果您使用CocoaPods 方法([CocoaPods method]),请将模块保存在与现有 iOS 应用相同的父目录中。
从 Flutter 模块目录中,您可以运行与在任何其他 Flutter 项目中相同的 flutter
命令,例如 flutter run
或 flutter build ios
。您还可以使用 Flutter 和 Dart 插件在VS Code(VS Code) 或Android Studio/IntelliJ(Android Studio/IntelliJ) 中运行该模块。此项目包含在将其嵌入到现有 iOS 应用之前,模块的单视图示例版本。这有助于测试代码中仅 Flutter 的部分。
组织您的模块
#my_flutter
模块目录结构类似于典型的 Flutter 应用。
my_flutter/
├── .ios/
│ ├── Runner.xcworkspace
│ └── Flutter/podhelper.rb
├── lib/
│ └── main.dart
├── test/
└── pubspec.yaml
您的 Dart 代码应添加到 lib/
目录中。您的 Flutter 依赖项、包和插件必须添加到 pubspec.yaml
文件中。
.ios/
隐藏子文件夹包含一个 Xcode 工作区,您可以在其中运行模块的独立版本。此包装项目引导您的 Flutter 代码。它包含一些辅助脚本,以方便构建框架或使用 CocoaPods 将模块嵌入到现有应用程序中。
将 Flutter 模块嵌入到您的 iOS 应用中
#开发 Flutter 模块后,您可以使用页面顶部表格中描述的方法将其嵌入。
您可以在模拟器或真实设备上以 调试 模式运行,在真实设备上以 发布 模式运行。
使用 CocoaPods 和 Flutter SDK
#方法
#此方法首先使用 CocoaPods 嵌入 Flutter 模块。 CocoaPods 管理 Swift 项目的依赖项,包括 Flutter 代码和插件。 每次 Xcode 构建应用程序时, CocoaPods 都会嵌入 Flutter 模块。
这允许使用 Flutter 模块的最新版本进行快速迭代,无需在 Xcode 之外运行其他命令。
要了解有关 CocoaPods 的更多信息, 请查阅CocoaPods 入门指南。
观看视频
#如果观看视频可以帮助您学习, 此视频介绍了如何将 Flutter 添加到 iOS 应用程序中:
Step by step on how to add Flutter to an existing iOS app
要求
#参与您项目的每个开发人员都必须安装本地版本的 Flutter SDK 和 CocoaPods。
示例项目结构
#本节假设您的现有应用程序和 Flutter 模块位于兄弟目录中。 如果您有不同的目录结构, 请调整相对路径。 示例目录结构如下所示:
/path/to/MyApp
├── my_flutter/
│ └── .ios/
│ └── Flutter/
│ └── podhelper.rb
└── MyApp/
└── Podfile
更新您的 Podfile
#将您的 Flutter 模块添加到您的 Podfile 配置文件中。 本节假设您将您的 Swift 应用程序命名为 MyApp
。
(可选) 如果您的现有应用程序缺少
Podfile
配置文件, 请导航到应用程序目录的根目录。 使用pod init
命令创建Podfile
文件。更新您的
Podfile
配置文件。在
platform
声明之后添加以下几行。MyApp/Podfilerubyflutter_application_path = '../my_flutter' load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')
对于需要嵌入 Flutter 的每个Podfile target, 请调用
install_all_flutter_pods(flutter_application_path)
方法。 在上一步骤中的设置之后添加这些调用。MyApp/Podfilerubytarget 'MyApp' do install_all_flutter_pods(flutter_application_path) end
在
Podfile
的post_install
块中, 调用flutter_post_install(installer)
。 此块应为Podfile
配置文件中的最后一个块。MyApp/Podfilerubypost_install do |installer| flutter_post_install(installer) if defined?(flutter_post_install) end
要查看示例 Podfile
,请参阅此Flutter Podfile 示例。
嵌入您的框架
#在构建时,Xcode 将您的 Dart 代码、每个 Flutter 插件和 Flutter 引擎打包到它们自己的 *.xcframework
包中。 然后,CocoaPod 的 podhelper.rb
脚本将这些 *.xcframework
包嵌入到您的项目中。
Flutter.xcframework
包含 Flutter 引擎。App.xcframework
包含此项目的已编译 Dart 代码。<plugin>.xcframework
包含一个 Flutter 插件。
要将 Flutter 引擎、您的 Dart 代码和您的 Flutter 插件嵌入到您的 iOS 应用程序中,请完成以下步骤。
刷新您的 Flutter 插件。
如果您更改了
pubspec.yaml
文件中的 Flutter 依赖项, 请在您的 Flutter 模块目录中运行flutter pub get
。 这将刷新podhelper.rb
脚本读取的插件列表。flutter pub get
使用 CocoaPods 嵌入插件和框架。
导航到您的 iOS 应用程序项目
/path/to/MyApp/MyApp
。使用
pod install
命令。pod install
您的 iOS 应用程序的 Debug 和 Release 构建配置会嵌入相应的针对该构建模式的 Flutter 组件。
构建项目。
在 Xcode 中打开
MyApp.xcworkspace
。验证您正在打开
MyApp.xcworkspace
而不是MyApp.xcodeproj
。.xcworkspace
文件包含 CocoaPod 依赖项,而.xcodeproj
不包含。选择 Product > Build 或按 Cmd + B。
在 Xcode 中链接和嵌入框架
#方法
#在第二种方法中,编辑您现有的 Xcode 项目,生成必要的框架,并将它们嵌入到您的应用中。Flutter 为 Flutter 本身、您的已编译 Dart 代码以及您的每个 Flutter 插件生成 iOS 框架。嵌入这些框架并更新您现有应用程序的构建设置。
要求
#此方法不需要额外的软件或硬件要求。在以下用例中使用此方法:
- 您的团队成员无法安装 Flutter SDK 和 CocoaPods
- 您不想在现有的 iOS 应用中使用 CocoaPods 作为依赖项管理器
限制
#Flutter无法处理使用xcframeworks的公共依赖项。如果宿主应用和Flutter模块的插件都定义了相同的pod依赖项,并且您使用此选项集成Flutter模块,则会产生错误。这些错误包括诸如“多个命令生成'CommonDependency.framework'”之类的错误。
为了解决这个问题,请将Flutter模块中每个插件的podspec
文件中的每个插件源链接到宿主应用的Podfile
。链接源代码而不是插件的xcframework
框架。下一节将解释如何生成该框架。
为了防止出现公共依赖项存在时发生的错误,请使用flutter build ios-framework
和--no-plugins
标志。
示例项目结构
#以下示例假设您希望将框架生成到 /path/to/MyApp/Flutter/
。
flutter build ios-framework --output=/path/to/MyApp/Flutter/
每次更改 Flutter 模块中的代码时都运行此命令。
生成的项目结构应类似于此目录树。
/path/to/MyApp/
└── Flutter/
├── Debug/
│ ├── Flutter.xcframework
│ ├── App.xcframework
│ ├── FlutterPluginRegistrant.xcframework (仅当您拥有包含 iOS 平台代码的插件时)
│ └── example_plugin.xcframework (每个插件都是一个单独的框架)
├── Profile/
│ ├── Flutter.xcframework
│ ├── App.xcframework
│ ├── FlutterPluginRegistrant.xcframework
│ └── example_plugin.xcframework
└── Release/
├── Flutter.xcframework
├── App.xcframework
├── FlutterPluginRegistrant.xcframework
└── example_plugin.xcframework
步骤
#您如何在 Xcode 中将生成的框架链接、嵌入或同时进行链接和嵌入到您现有的应用中,取决于框架的类型。
- 链接和嵌入动态框架。
- 链接静态框架。切勿嵌入它们。
Flutter 插件可能会生成静态或动态框架。链接静态框架, 绝不要 嵌入它们。
如果您将静态框架嵌入到您的 iOS 应用中,则无法将该应用发布到 App Store。发布时会失败,并出现 Found an unexpected Mach-O header code
归档错误。
链接所有框架
#要链接必要的框架,请按照以下步骤操作。
选择要链接的框架。
在 项目导航器 中,点击您的项目。
点击 构建阶段 选项卡。
展开 使用库链接二进制文件 。
在 Xcode 中展开 使用库链接二进制文件 构建阶段 点击**+**(加号)。
点击添加其他...,然后点击添加文件...。
在**选择要添加的框架和库:**对话框中,导航到
/path/to/MyApp/Flutter/Release/
目录。命令点击该目录中的框架,然后点击 打开 。
在 Xcode 的**选择要添加的框架和库:**对话框中选择要链接的框架
更新库的路径以适应构建模式。
启动访达。
导航到
/path/to/MyApp/
目录。右键点击
MyApp.xcodeproj
并选择 显示包内容 。使用 Xcode 打开
project.pbxproj
。该文件将在 Xcode 的文本编辑器中打开。这也会锁定 项目导航器 ,直到您关闭文本编辑器。在 Xcode 文本编辑器中打开的 project-pbxproj
文件在
/* Begin PBXFileReference section */
中找到类似于以下文本的行。text312885572C1A441C009F74FF /* Flutter.xcframework */ = { isa = PBXFileReference; expectedSignature = "AppleDeveloperProgram:S8QB4VV633:FLUTTER.IO LLC"; lastKnownFileType = wrapper.xcframework; name = Flutter.xcframework; path = Flutter/Release/Flutter.xcframework; sourceTree = "<group>"; }; 312885582C1A441C009F74FF /* App.xcframework */ = { isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = App.xcframework; path = Flutter/Release/App.xcframework; sourceTree = "<group>"; };
将上一步中突出显示的
Release
文本更改为$(CONFIGURATION)
。还要将路径用引号括起来。text312885572C1A441C009F74FF /* Flutter.xcframework */ = { isa = PBXFileReference; expectedSignature = "AppleDeveloperProgram:S8QB4VV633:FLUTTER.IO LLC"; lastKnownFileType = wrapper.xcframework; name = Flutter.xcframework; path = "Flutter/$(CONFIGURATION)/Flutter.xcframework"; sourceTree = "<group>"; }; 312885582C1A441C009F74FF /* App.xcframework */ = { isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = App.xcframework; path = "Flutter/$(CONFIGURATION)/App.xcframework"; sourceTree = "<group>"; };
更新搜索路径。
点击 构建设置 选项卡。
导航到 搜索路径 。
双击 框架搜索路径 右侧。
在组合框中,点击**+**(加号)。
输入
$(inherited)
。 然后按Enter。点击**+**(加号)。
输入
$(PROJECT_DIR)/Flutter/$(CONFIGURATION)/
然后按Enter。在 Xcode 中更新 框架搜索路径
链接框架后,它们应该显示在目标的 常规 设置的框架、库和嵌入式内容部分中。
嵌入动态框架
#要嵌入动态框架,请完成以下步骤。
导航到常规 > 框架、库和嵌入式内容。
点击每个动态框架并选择 嵌入和签名 。
在 Xcode 中为每个框架选择 嵌入和签名 不要包含任何静态框架,包括
FlutterPluginRegistrant.xcframework
。点击 构建阶段 选项卡。
展开 嵌入框架 。您的动态框架应该显示在该部分中。
Xcode 中展开的 嵌入框架 构建阶段 构建项目。
在 Xcode 中打开
MyApp.xcworkspace
。验证您正在打开
MyApp.xcworkspace
而不是MyApp.xcodeproj
。.xcworkspace
文件包含 CocoaPod 依赖项,而.xcodeproj
文件不包含。选择产品 > 构建或按Cmd + B。
在 Xcode 和 Flutter 框架中使用框架作为 podspec
#方法
#此方法生成 Flutter 作为 CocoaPods podspec,而不是将大型 Flutter.xcframework
分发给其他开发者、机器或持续集成系统。Flutter 仍然会为您的已编译 Dart 代码和每个 Flutter 插件生成 iOS 框架。嵌入这些框架并更新您现有应用程序的构建设置。
需求
#此方法不需要额外的软件或硬件要求。在以下用例中使用此方法:
- 您的团队成员无法安装 Flutter SDK 和 CocoaPods
- 您不想在现有的 iOS 应用中使用 CocoaPods 作为依赖项管理器
限制
#Flutter无法处理使用xcframeworks的公共依赖项。如果宿主应用和Flutter模块的插件都定义了相同的pod依赖项,并且您使用此选项集成Flutter模块,则会产生错误。这些错误包括诸如“多个命令生成'CommonDependency.framework'”之类的错误。
为了解决这个问题,请将Flutter模块中每个插件的podspec
文件中的每个插件源链接到宿主应用的Podfile
。链接源代码而不是插件的xcframework
框架。下一节将解释如何生成该框架。
为了防止出现公共依赖项存在时发生的错误,请使用flutter build ios-framework
和--no-plugins
标志。
此方法仅适用于 beta
或 stable
发布渠道。
示例项目结构
#以下示例假设您希望将框架生成到 /path/to/MyApp/Flutter/
。
flutter build ios-framework --output=/path/to/MyApp/Flutter/
每次更改 Flutter 模块中的代码时都运行此命令。
生成的项目结构应类似于此目录树。
/path/to/MyApp/
└── Flutter/
├── Debug/
│ ├── Flutter.xcframework
│ ├── App.xcframework
│ ├── FlutterPluginRegistrant.xcframework (仅当您拥有包含 iOS 平台代码的插件时)
│ └── example_plugin.xcframework (每个插件都是一个单独的框架)
├── Profile/
│ ├── Flutter.xcframework
│ ├── App.xcframework
│ ├── FlutterPluginRegistrant.xcframework
│ └── example_plugin.xcframework
└── Release/
├── Flutter.xcframework
├── App.xcframework
├── FlutterPluginRegistrant.xcframework
└── example_plugin.xcframework
将 Flutter 引擎添加到您的 Podfile
#使用 CocoaPods 的宿主应用可以将其 Podfile 中添加 Flutter 引擎。
pod 'Flutter', :podspec => '/path/to/MyApp/Flutter/[build mode]/Flutter.podspec'
链接和嵌入应用和插件框架
#Flutter 插件可能会生成静态或动态框架。链接静态框架, 绝不要 嵌入它们。
如果您将静态框架嵌入到您的 iOS 应用中,则无法将该应用发布到 App Store。发布时会失败,并出现 Found an unexpected Mach-O header code
归档错误。
链接所有框架
#要链接必要的框架,请按照以下步骤操作。
选择要链接的框架。
在 项目导航器 中,点击您的项目。
点击 构建阶段 选项卡。
展开 使用库链接二进制文件 。
在 Xcode 中展开 使用库链接二进制文件 构建阶段 点击**+**(加号)。
点击添加其他...,然后点击添加文件...。
在**选择要添加的框架和库:**对话框中,导航到
/path/to/MyApp/Flutter/Release/
目录。命令点击该目录中的框架,然后点击 打开 。
在 Xcode 的**选择要添加的框架和库:**对话框中选择要链接的框架
更新库的路径以适应构建模式。
启动访达。
导航到
/path/to/MyApp/
目录。右键点击
MyApp.xcodeproj
并选择 显示包内容 。使用 Xcode 打开
project.pbxproj
。该文件将在 Xcode 的文本编辑器中打开。这也会锁定 项目导航器 ,直到您关闭文本编辑器。在 Xcode 文本编辑器中打开的 project-pbxproj
文件在
/* Begin PBXFileReference section */
中找到类似于以下文本的行。text312885572C1A441C009F74FF /* Flutter.xcframework */ = { isa = PBXFileReference; expectedSignature = "AppleDeveloperProgram:S8QB4VV633:FLUTTER.IO LLC"; lastKnownFileType = wrapper.xcframework; name = Flutter.xcframework; path = Flutter/Release/Flutter.xcframework; sourceTree = "<group>"; }; 312885582C1A441C009F74FF /* App.xcframework */ = { isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = App.xcframework; path = Flutter/Release/App.xcframework; sourceTree = "<group>"; };
将上一步中突出显示的
Release
文本更改为$(CONFIGURATION)
。还要将路径用引号括起来。text312885572C1A441C009F74FF /* Flutter.xcframework */ = { isa = PBXFileReference; expectedSignature = "AppleDeveloperProgram:S8QB4VV633:FLUTTER.IO LLC"; lastKnownFileType = wrapper.xcframework; name = Flutter.xcframework; path = "Flutter/$(CONFIGURATION)/Flutter.xcframework"; sourceTree = "<group>"; }; 312885582C1A441C009F74FF /* App.xcframework */ = { isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = App.xcframework; path = "Flutter/$(CONFIGURATION)/App.xcframework"; sourceTree = "<group>"; };
更新搜索路径。
点击 构建设置 选项卡。
导航到 搜索路径 。
双击 框架搜索路径 右侧。
在组合框中,点击**+**(加号)。
输入
$(inherited)
。 然后按Enter。点击**+**(加号)。
输入
$(PROJECT_DIR)/Flutter/$(CONFIGURATION)/
然后按Enter。在 Xcode 中更新 框架搜索路径
链接框架后,它们应该显示在目标的 常规 设置的框架、库和嵌入式内容部分中。
嵌入动态框架
#要嵌入动态框架,请完成以下步骤。
导航到常规 > 框架、库和嵌入式内容。
点击每个动态框架并选择 嵌入和签名 。
在 Xcode 中为每个框架选择 嵌入和签名 不要包含任何静态框架,包括
FlutterPluginRegistrant.xcframework
。点击 构建阶段 选项卡。
展开 嵌入框架 。您的动态框架应该显示在该部分中。
Xcode 中展开的 嵌入框架 构建阶段 构建项目。
在 Xcode 中打开
MyApp.xcworkspace
。验证您正在打开
MyApp.xcworkspace
而不是MyApp.xcodeproj
。.xcworkspace
文件包含 CocoaPod 依赖项,而.xcodeproj
文件不包含。选择产品 > 构建或按Cmd + B。
设置本地网络隐私权限
#在 iOS 14 及更高版本上,在 iOS 应用的 调试 版本中启用 Dart 多播 DNS 服务。这会添加使用 flutter attach
的调试功能,例如热重载和 DevTools([debugging functionalities such as hot-reload and DevTools])。
要仅在应用的调试版本中设置本地网络隐私权限,请为每个构建配置创建一个单独的 Info.plist
。SwiftUI 项目从没有 Info.plist
文件开始。如果需要创建属性列表,可以通过 Xcode 或文本编辑器进行操作。以下说明假设默认的 调试 和发布。根据您的应用构建配置需要调整名称。
创建一个新的属性列表。
在 Xcode 中打开您的项目。
在 项目导航器 中,单击项目名称。
在编辑器窗格中的 目标 列表中,单击您的应用。
单击 信息 选项卡。
展开自定义 iOS 目标属性。
右键单击列表,然后选择 添加行 。
从下拉菜单中,选择Bonjour 服务。这会在项目目录中创建一个名为
Info
的新属性列表。这在 Finder 中显示为Info.plist
。
将
Info.plist
重命名为Info-Debug.plist
单击左侧项目列表中的Info文件。
在右侧的 标识和类型 面板中,将 名称 从
Info.plist
更改为Info-Debug.plist
。
创建发布属性列表。
在 项目导航器 中,单击
Info-Debug.plist
。选择 文件 >复制...。您也可以按 Cmd + Shift + S。
在对话框中,将**另存为:**字段设置为
Info-Release.plist
,然后单击 保存 。
将必要的属性添加到 调试 属性列表。
在 项目导航器 中,单击
Info-Debug.plist
。将字符串值
_dartVmService._tcp
添加到Bonjour 服务数组。(可选) 要设置您所需的自定义权限对话框文本,请添加键隐私 - 本地网络使用说明。
添加了Bonjour 服务 和 隐私 - 本地网络使用说明键的 Info-Debug
属性列表
设置目标以对不同的构建模式使用不同的属性列表。
在 项目导航器 中,单击您的项目。
单击 构建设置 选项卡。
单击 全部 和组合子选项卡。
在搜索框中,键入
plist
。这会将设置限制为包含属性列表的那些设置。向下滚动列表,直到看到 打包 。
单击Info.plist 文件设置。
将Info.plist 文件值从
path/to/Info.plist
更改为path/to/Info-$(CONFIGURATION).plist
。更新 Info.plist
构建设置以使用特定于构建模式的属性列表这将解析为 调试 中的
path/to/Info-Debug.plist
和 发布 中的path/to/Info-Release.plist
。更新的Info.plist 文件构建设置显示配置变体
从 构建阶段 中删除 发布 属性列表。
在 项目导航器 中,单击您的项目。
单击 构建阶段 选项卡。
展开 复制捆绑资源 。
如果此列表包含
Info-Release.plist
,请单击它,然后单击其下的 -(减号)以将其从资源列表中删除。显示Info-Release.plist 设置的 复制捆绑包构建阶段。删除此设置。
调试应用加载的第一个 Flutter 屏幕会提示本地网络权限。
单击 确定 。
(可选) 要在应用加载前授予权限,请启用设置 > 隐私 > 本地网络 > 您的应用。
缓解 Apple 硅芯片 Mac 的已知问题
#在运行 Apple 硅芯片的 Mac上,主机应用会为 arm64
模拟器构建。虽然 Flutter 支持 arm64
模拟器,但某些插件可能不支持。如果您使用其中一个插件,您可能会看到类似架构 arm64 的未定义符号的编译错误。如果发生这种情况,请从主机应用中的模拟器架构中排除 arm64
。
在 项目导航器 中,单击您的项目。
单击 构建设置 选项卡。
单击 全部 和组合子选项卡。
在 架构 下,单击 排除的架构 。
展开以查看可用的构建配置。
单击 调试 。
单击**+**(加号)。
选择iOS 模拟器。
双击任何 iOS 模拟器 SDK的值列。
单击**+**(加号)。
在调试 > 任何 iOS 模拟器 SDK对话框中键入
arm64
。将 arm64
添加为应用的排除架构按 Esc 关闭此对话框。
对 发布 构建模式重复这些步骤。
对任何 iOS 单元测试目标重复此操作。
下一步
#您现在可以[将 Flutter 屏幕添加到]([add a Flutter screen])您的现有 iOS 应用中。
除非另有说明,否则本网站上的文档反映的是 Flutter 的最新稳定版本。页面最后更新于 2025-01-30。 查看源代码 或 报告问题。