将 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系统要求,并安装Xcode。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方法,请将模块保存在与现有iOS应用相同的父目录中。
从Flutter模块目录中,您可以运行与在任何其他Flutter项目中相同的flutter
命令,例如flutter run
或flutter build ios
。您还可以使用Flutter和Dart插件在VS Code或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应用中
要求
#每个参与项目的开发人员都必须安装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目标,请调用
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嵌入插件和框架。
导航到位于
/path/to/MyApp/MyApp
的iOS应用项目。使用
pod install
命令。pod install
iOS应用的调试和发布构建配置会嵌入相应的该构建模式的Flutter组件。
构建项目。
在Xcode中打开
MyApp.xcworkspace
。验证您正在打开
MyApp.xcworkspace
而不是MyApp.xcodeproj
。.xcworkspace
文件包含CocoaPod依赖项,.xcodeproj
文件不包含。选择产品>构建或按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 (only if you have plugins with iOS platform code)
│ └── example_plugin.xcframework (each plugin is a separate framework)
├── 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。发布将失败并出现找到意外的Mach-O头代码
归档错误。
链接所有框架
#要链接必要的框架,请按照以下步骤操作。
选择要链接的框架。
在项目导航器中,单击您的项目。
单击构建阶段选项卡。
展开使用库链接二进制文件。
在Xcode中展开使用库链接二进制文件构建阶段 单击+(加号)。
单击添加其他...,然后单击添加文件...。
在选择要添加的框架和库:对话框中,导航到
/path/to/MyApp/Flutter/Release/
目录。按住Command键单击该目录中的框架,然后单击打开。
从Xcode中的选择要添加的框架和库:对话框中选择要链接的框架
更新库的路径以适应构建模式。
启动Finder。
导航到
/path/to/MyApp/
目录。右键单击
MyApp.xcodeproj
并选择显示包内容。使用Xcode打开
project.pbxproj
。该文件将在Xcode的文本编辑器中打开。这也会锁定项目导航器,直到您关闭文本编辑器。在Xcode文本编辑器中打开的 project-pbxproj
文件在
/* Begin PBXFileReference section */
中找到类似于以下文本的行。文本312885572C1A441C009F74FF /* 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)
。还要将路径括在引号中。文本312885572C1A441C009F74FF /* 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>"; };
更新搜索路径。
点击**Build Settings**选项卡。
导航到**Search Paths**
双击**Framework Search Paths**右侧。
在组合框中,点击**+**(加号)。
输入
$(inherited)
,然后按Enter。单击+(加号)。
输入
$(PROJECT_DIR)/Flutter/$(CONFIGURATION)/
,然后按Enter。在 Xcode 中更新**Framework Search Paths**
链接框架后,它们应该会显示在目标的**General**设置中的**Frameworks, Libraries, and Embedded Content**部分。
嵌入动态框架
#要嵌入动态框架,请完成以下步骤。
导航到**General** > **Frameworks, Libraries, and Embedded Content**。
点击每个动态框架并选择**Embed & Sign**。
在 Xcode 中为每个框架选择**Embed & Sign** 不要包含任何静态框架,包括
FlutterPluginRegistrant.xcframework
。单击构建阶段选项卡。
展开**Embed Frameworks**。您的动态框架应该会显示在该部分。
Xcode 中展开的**Embed Frameworks**构建阶段 构建项目。
在Xcode中打开
MyApp.xcworkspace
。验证您正在打开
MyApp.xcworkspace
而不是MyApp.xcodeproj
。.xcworkspace
文件包含CocoaPod依赖项,.xcodeproj
文件不包含。选择**Product** > **Build**或按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 (only if you have plugins with iOS platform code)
│ └── example_plugin.xcframework (each plugin is a separate framework)
├── Profile/
│ ├── Flutter.xcframework
│ ├── App.xcframework
│ ├── FlutterPluginRegistrant.xcframework
│ └── example_plugin.xcframework
└── Release/
├── Flutter.xcframework
├── App.xcframework
├── FlutterPluginRegistrant.xcframework
└── example_plugin.xcframework
将 Flutter 引擎添加到您的 Podfile
#使用 CocoaPods 的宿主应用程序可以将 Flutter 引擎添加到其 Podfile 中。
pod 'Flutter', :podspec => '/path/to/MyApp/Flutter/[build mode]/Flutter.podspec'
链接和嵌入应用程序和插件框架
#Flutter插件可能会生成静态或动态框架。链接静态框架,切勿嵌入它们。
如果将静态框架嵌入到iOS应用中,则无法将该应用发布到App Store。发布将失败并出现找到意外的Mach-O头代码
归档错误。
链接所有框架
#要链接必要的框架,请按照以下步骤操作。
选择要链接的框架。
在项目导航器中,单击您的项目。
单击构建阶段选项卡。
展开使用库链接二进制文件。
在Xcode中展开使用库链接二进制文件构建阶段 单击+(加号)。
单击添加其他...,然后单击添加文件...。
在选择要添加的框架和库:对话框中,导航到
/path/to/MyApp/Flutter/Release/
目录。按住Command键单击该目录中的框架,然后单击打开。
从Xcode中的选择要添加的框架和库:对话框中选择要链接的框架
更新库的路径以适应构建模式。
启动Finder。
导航到
/path/to/MyApp/
目录。右键单击
MyApp.xcodeproj
并选择显示包内容。使用Xcode打开
project.pbxproj
。该文件将在Xcode的文本编辑器中打开。这也会锁定项目导航器,直到您关闭文本编辑器。在Xcode文本编辑器中打开的 project-pbxproj
文件在
/* Begin PBXFileReference section */
中找到类似于以下文本的行。文本312885572C1A441C009F74FF /* 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)
。还要将路径括在引号中。文本312885572C1A441C009F74FF /* 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>"; };
更新搜索路径。
点击**Build Settings**选项卡。
导航到**Search Paths**
双击**Framework Search Paths**右侧。
在组合框中,点击**+**(加号)。
输入
$(inherited)
,然后按Enter。单击+(加号)。
输入
$(PROJECT_DIR)/Flutter/$(CONFIGURATION)/
,然后按Enter。在 Xcode 中更新**Framework Search Paths**
链接框架后,它们应该会显示在目标的**General**设置中的**Frameworks, Libraries, and Embedded Content**部分。
嵌入动态框架
#要嵌入动态框架,请完成以下步骤。
导航到**General** > **Frameworks, Libraries, and Embedded Content**。
点击每个动态框架并选择**Embed & Sign**。
在 Xcode 中为每个框架选择**Embed & Sign** 不要包含任何静态框架,包括
FlutterPluginRegistrant.xcframework
。单击构建阶段选项卡。
展开**Embed Frameworks**。您的动态框架应该会显示在该部分。
Xcode 中展开的**Embed Frameworks**构建阶段 构建项目。
在Xcode中打开
MyApp.xcworkspace
。验证您正在打开
MyApp.xcworkspace
而不是MyApp.xcodeproj
。.xcworkspace
文件包含CocoaPod依赖项,.xcodeproj
文件不包含。选择**Product** > **Build**或按Cmd + B。
设置本地网络隐私权限
#在 iOS 14 及更高版本上,在 iOS 应用程序的**Debug**版本中启用 Dart 多播 DNS 服务。这将添加 诸如热重载和 DevTools 等调试功能,以便使用flutter attach
。
要仅在应用程序的 Debug 版本中设置本地网络隐私权限,请为每个构建配置创建一个单独的Info.plist
。SwiftUI 项目从没有Info.plist
文件开始。如果您需要创建属性列表,可以通过 Xcode 或文本编辑器来完成。以下说明假设默认的**Debug**和**Release**。根据您的应用程序的构建配置调整名称。
创建一个新的属性列表。
在 Xcode 中打开您的项目。
在**Project Navigator**中,点击项目名称。
在编辑器窗格中的**Targets**列表中,点击您的应用程序。
点击**Info**选项卡。
展开**Custom iOS Target Properties**。
右键点击列表并选择**Add Row**。
从下拉菜单中,选择**Bonjour Services**。这将在项目目录中创建一个名为
Info
的新属性列表。这在 Finder 中显示为Info.plist
。
将
Info.plist
重命名为Info-Debug.plist
点击左侧项目列表中的**Info**文件。
在右侧的**Identity and Type**面板中,将**Name**从
Info.plist
更改为Info-Debug.plist
。
创建一个 Release 属性列表。
在**Project Navigator**中,点击
Info-Debug.plist
。选择**File** > **Duplicate...**。
您也可以按Cmd + Shift + S。在对话框中,将**Save As:**字段设置为
Info-Release.plist
,然后点击**Save**。
将必要的属性添加到**Debug**属性列表。
在**Project Navigator**中,点击
Info-Debug.plist
。将字符串值
_dartVmService._tcp
添加到**Bonjour Services**数组。(可选)要设置您所需的自定义权限对话框文本,请添加键**Privacy - Local Network Usage Description**。
添加了**Bonjour Services**和**Privacy - Local Network Usage Description**键的 Info-Debug
属性列表
设置目标以对不同的构建模式使用不同的属性列表。
在项目导航器中,单击您的项目。
点击**Build Settings**选项卡。
点击**All**和**Combined**子选项卡。
在搜索框中,输入
plist
。
这将设置限制为包含属性列表的那些设置。滚动浏览列表,直到看到**Packaging**。
点击**Info.plist File**设置。
将**Info.plist File**值从
path/to/Info.plist
更改为path/to/Info-$(CONFIGURATION).plist
。更新 Info.plist
构建设置以使用特定于构建模式的属性列表这将解析为**Debug**中的路径**Info-Debug.plist**和**Release**中的路径**Info-Release.plist**。
更新后的**Info.plist File**构建设置显示配置变化
从**Build Phases**中删除**Release**属性列表。
在项目导航器中,单击您的项目。
单击构建阶段选项卡。
展开**Copy Bundle Resources**。
如果此列表包含
Info-Release.plist
,请点击它,然后点击其下方的**-**(减号)以从资源列表中删除属性列表。显示**Info-Release.plist**设置的**Copy Bundle**构建阶段。删除此设置。
调试应用程序加载的第一个 Flutter 屏幕会提示您进行本地网络权限。
点击**OK**。
(可选)要在应用程序加载前授予权限,请启用**Settings > Privacy > Local Network > Your App**。
缓解 Apple Silicon Mac 上的已知问题
#在 运行 Apple Silicon 的 Mac 上,宿主应用程序将为arm64
模拟器构建。虽然 Flutter 支持arm64
模拟器,但某些插件可能不支持。如果您使用其中一个插件,您可能会看到类似于**Undefined symbols for architecture arm64**的编译错误。如果发生这种情况,请从宿主应用程序中的模拟器架构中排除arm64
。
在项目导航器中,单击您的项目。
点击**Build Settings**选项卡。
点击**All**和**Combined**子选项卡。
在**Architectures**下,点击**Excluded Architectures**。
展开以查看可用的构建配置。
点击**Debug**。
点击**+**(加号)。
选择**iOS Simulator**。
双击**Any iOS Simulator SDK**的值列。
点击**+**(加号)。
在**Debug > Any iOS Simulator SDK**对话框中输入
arm64
。将 arm64
添加为应用程序的排除架构按Esc关闭此对话框。
对**Release**构建模式重复这些步骤。
对任何 iOS 单元测试目标重复。
后续步骤
#您现在可以 将 Flutter 屏幕添加到您现有的 iOS 应用程序。
除非另有说明,否则本网站上的文档反映了 Flutter 的最新稳定版本。页面上次更新于 2024-08-06。 查看源代码 或 报告问题.