面向插件作者的 Swift Package Manager 指南
如何为 iOS 和 macOS 插件添加 Swift Package Manager 兼容性
Flutter 的 Swift Package Manager 集成具有多项优势
- 提供对 Swift 包生态系统的访问权限。Flutter 插件可以使用不断增长的 Swift 包 生态系统!
- 简化 Flutter 安装。Swift Package Manager 与 Xcode 捆绑在一起。未来,你将不再需要安装 Ruby 和 CocoaPods 即可为 iOS 或 macOS 开发。
如何开启 Swift Package Manager
#Flutter 的 Swift Package Manager 支持默认处于关闭状态。要开启它:
-
升级到最新的 Flutter SDK
shflutter upgrade -
开启 Swift Package Manager 功能
shflutter config --enable-swift-package-manager
使用 Flutter CLI 运行应用会迁移项目以添加 Swift Package Manager 集成。这会使你的项目下载 Flutter 插件所依赖的 Swift 包。具有 Swift Package Manager 集成的应用需要 Flutter 3.24 或更高版本。若要使用旧版本的 Flutter,你需要从应用中移除 Swift Package Manager 集成。
对于尚不支持 Swift Package Manager 的依赖项,Flutter 会回退到 CocoaPods。
如何关闭 Swift Package Manager
#禁用 Swift Package Manager 会导致 Flutter 对所有依赖项使用 CocoaPods。但是,Swift Package Manager 仍会保留在你的项目中。若要从项目中完全移除 Swift Package Manager 集成,请遵循如何移除 Swift Package Manager 集成中的说明。
为单个项目关闭
#在项目的 pubspec.yaml 文件中,在 flutter 部分下,将 config 子部分中的 enable-swift-package-manager 设置为 false。
# The following section is specific to Flutter packages.
flutter:
config:
enable-swift-package-manager: false
这会为该项目的所有贡献者关闭 Swift Package Manager。
全局关闭所有项目
#运行以下命令
flutter config --no-enable-swift-package-manager
这会为当前用户关闭 Swift Package Manager。
如果项目与 Swift Package Manager 不兼容,所有贡献者都需要运行此命令。
如何为现有的 Flutter 插件添加 Swift Package Manager 支持
#本指南展示了如何为已支持 CocoaPods 的插件添加 Swift Package Manager 支持。这确保了插件可被所有 Flutter 项目使用。
在另行通知前,Flutter 插件应同时支持 Swift Package Manager 和 CocoaPods。
Swift Package Manager 的采用将是循序渐进的。不支持 CocoaPods 的插件将无法被尚未迁移到 Swift Package Manager 的项目使用。不支持 Swift Package Manager 的插件可能会给已迁移的项目带来问题。
在本指南中,将 plugin_name 替换为你的插件名称。下方的示例使用 ios,请根据需要将 ios 替换为 macos/darwin。
-
首先在
ios、macos和/或darwin目录下创建一个目录。将此新目录命名为平台包的名称。plugin_name/
ios/
- …
- plugin_name/
-
在此新目录中,创建以下文件/目录:
Package.swift(文件)Sources(目录)Sources/plugin_name(目录)
你的插件结构应如下所示:
plugin_name/
ios/
- …
plugin_name/
- Package.swift
Sources/
- plugin_name/
-
在
Package.swift文件中使用以下模板Package.swiftswift// swift-tools-version: 5.9 // The swift-tools-version declares the minimum version of Swift required to build this package. import PackageDescription let package = Package( // TODO: Update your plugin name. name: "plugin_name", platforms: [ // TODO: Update the platforms your plugin supports. // If your plugin only supports iOS, remove `.macOS(...)`. // If your plugin only supports macOS, remove `.iOS(...)`. .iOS("13.0"), .macOS("10.15") ], products: [ // TODO: Update your library and target names. // If the plugin name contains "_", replace with "-" for the library name. .library(name: "plugin-name", targets: ["plugin_name"]) ], dependencies: [ .package(name: "FlutterFramework", path: "../FlutterFramework") ], targets: [ .target( // TODO: Update your target name. name: "plugin_name", dependencies: [ .product(name: "FlutterFramework", package: "FlutterFramework") ], resources: [ // TODO: If your plugin requires a privacy manifest // (e.g. if it uses any required reason APIs), update the PrivacyInfo.xcprivacy file // to describe your plugin's privacy impact, and then uncomment this line. // For more information, see: // https://developer.apple.com/documentation/bundleresources/privacy_manifest_files // .process("PrivacyInfo.xcprivacy"), // TODO: If you have other resources that need to be bundled with your plugin, refer to // the following instructions to add them: // https://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package ] ) ] ) -
更新
Package.swift文件中的受支持平台。Package.swiftswiftplatforms: [ // TODO: Update the platforms your plugin supports. // If your plugin only supports iOS, remove `.macOS(...)`. // If your plugin only supports macOS, remove `.iOS(...)`. .iOS("13.0"), .macOS("10.15") ], -
更新
Package.swift文件中的包、库和目标名称。Package.swiftswiftlet package = Package( // TODO: Update your plugin name. name: "plugin_name", platforms: [ .iOS("13.0"), .macOS("10.15") ], products: [ // TODO: Update your library and target names. // If the plugin name contains "_", replace with "-" for the library name .library(name: "plugin-name", targets: ["plugin_name"]) ], dependencies: [], targets: [ .target( // TODO: Update your target name. name: "plugin_name", dependencies: [], resources: [ // TODO: If your plugin requires a privacy manifest // (e.g. if it uses any required reason APIs), update the PrivacyInfo.xcprivacy file // to describe your plugin's privacy impact, and then uncomment this line. // For more information, see: // https://developer.apple.com/documentation/bundleresources/privacy_manifest_files // .process("PrivacyInfo.xcprivacy"), // TODO: If you have other resources that need to be bundled with your plugin, refer to // the following instructions to add them: // https://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package ] ) ] ) -
如果你的插件有
PrivacyInfo.xcprivacy文件,请将其移动到ios/plugin_name/Sources/plugin_name/PrivacyInfo.xcprivacy,并取消注释Package.swift文件中的资源配置。Package.swiftswiftresources: [ // TODO: If your plugin requires a privacy manifest // (e.g. if it uses any required reason APIs), update the PrivacyInfo.xcprivacy file // to describe your plugin's privacy impact, and then uncomment this line. // For more information, see: // https://developer.apple.com/documentation/bundleresources/privacy_manifest_files .process("PrivacyInfo.xcprivacy"), // TODO: If you have other resources that need to be bundled with your plugin, refer to // the following instructions to add them: // https://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package ], -
将任何资源文件从
ios/Assets移动到ios/plugin_name/Sources/plugin_name(或其子目录)。如有必要,将这些资源文件添加到你的Package.swift文件中。更多说明,请参阅 https://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package。 -
将所有文件从
ios/Classes移动到ios/plugin_name/Sources/plugin_name。 -
Flutter 3.41 新功能! 添加 FlutterFramework 作为依赖项并更新 Dart/Flutter 版本。
更新
Package.swift以包含FlutterFrameworkPackage.swiftswiftdependencies: [ .package(name: "FlutterFramework", path: "../FlutterFramework") ], targets: [ .target( // TODO: Update your target name. name: "plugin_name", dependencies: [ .product(name: "FlutterFramework", package: "FlutterFramework") ],在
pubspec.yaml中,更新版本号为pubspec.yamlyamlenvironment: sdk: ^3.11.0 flutter: ">=3.41.0" -
ios/Assets、ios/Resources和ios/Classes目录现在应该是空的,可以删除。 -
如果你的插件使用了 Pigeon,请更新你的 Pigeon 输入文件。
pigeons/messages.dartdartkotlinOptions: KotlinOptions(), javaOut: 'android/app/src/main/java/io/flutter/plugins/Messages.java', javaOptions: JavaOptions(), swiftOut: 'ios/Classes/messages.g.swift', swiftOut: 'ios/plugin_name/Sources/plugin_name/messages.g.swift', swiftOptions: SwiftOptions(), -
使用你可能需要的任何自定义设置更新你的
Package.swift文件。在 Xcode 中打开
ios/plugin_name/目录。在 Xcode 中打开你的
Package.swift文件。确认 Xcode 没有为此文件产生任何警告或错误。如果你的
ios/plugin_name.podspec文件包含 CocoaPodsdependency,请将相应的 Swift Package Manager 依赖项添加到你的Package.swift文件中。如果你的包必须显式链接为
static或dynamic(Apple 不推荐),请更新 Product 以定义其类型。Package.swiftswiftproducts: [ .library(name: "plugin-name", type: .static, targets: ["plugin_name"]) ],进行其他自定义。有关如何编写
Package.swift文件的更多信息,请参阅 https://developer.apple.com/documentation/packagedescription。
-
更新你的
ios/plugin_name.podspec以指向新路径。ios/plugin_name.podspecrubys.source_files = 'Classes/**/*.swift' s.resource_bundles = {'plugin_name_privacy' => ['Resources/PrivacyInfo.xcprivacy']} s.source_files = 'plugin_name/Sources/plugin_name/**/*.swift' s.resource_bundles = {'plugin_name_privacy' => ['plugin_name/Sources/plugin_name/PrivacyInfo.xcprivacy']} -
更新从 Bundle 加载资源的方式,使用
Bundle.module。swift#if SWIFT_PACKAGE let settingsURL = Bundle.module.url(forResource: "image", withExtension: "jpg") #else let settingsURL = Bundle(for: Self.self).url(forResource: "image", withExtension: "jpg") #endif -
如果你的
.gitignore没有包含.build/和.swiftpm/目录,你需要更新你的.gitignore以包含它们:.gitignore.build/ .swiftpm/将插件的更改提交到你的版本控制系统。
-
验证插件在使用 CocoaPods 时仍然可以正常工作。
关闭 Swift Package Manager。
shflutter config --no-enable-swift-package-manager导航到插件的示例应用。
shcd path/to/plugin/example/确保插件的示例应用可以构建和运行。
shflutter run导航到插件的顶层目录。
shcd path/to/plugin/运行 CocoaPods 验证检查。
shpod lib lint ios/plugin_name.podspec --configuration=Debug --skip-tests --use-modular-headers --use-librariesshpod lib lint ios/plugin_name.podspec --configuration=Debug --skip-tests --use-modular-headers
-
验证插件在使用 Swift Package Manager 时可以正常工作。
开启 Swift Package Manager。
shflutter config --enable-swift-package-manager导航到插件的示例应用。
shcd path/to/plugin/example/确保插件的示例应用可以构建和运行。
shflutter run在 Xcode 中打开插件的示例应用。确保 Package Dependencies 显示在左侧的 Project Navigator 中。
-
验证测试通过。
如果你的插件有原生单元测试 (XCTest),请确保同时也更新了插件示例应用中的单元测试。
遵循测试插件的说明。
在本指南中,将 plugin_name 替换为你的插件名称。下方的示例使用 ios,请根据需要将 ios 替换为 macos/darwin。
-
首先在
ios、macos和/或darwin目录下创建一个目录。将此新目录命名为平台包的名称。plugin_name/
ios/
- …
- plugin_name/
-
在此新目录中,创建以下文件/目录:
Package.swift(文件)Sources(目录)Sources/plugin_name(目录)Sources/plugin_name/include(目录)Sources/plugin_name/include/plugin_name(目录)Sources/plugin_name/include/plugin_name/.gitkeep(文件)- 此文件确保目录被提交到版本库。如果目录中添加了其他文件,可以删除
.gitkeep文件。
- 此文件确保目录被提交到版本库。如果目录中添加了其他文件,可以删除
你的插件结构应如下所示:
plugin_name/
ios/
- …
plugin_name/
- Package.swift
Sources/plugin_name/include/plugin_name/
- .gitkeep/
-
在
Package.swift文件中使用以下模板Package.swiftswift// swift-tools-version: 5.9 // The swift-tools-version declares the minimum version of Swift required to build this package. import PackageDescription let package = Package( // TODO: Update your plugin name. name: "plugin_name", platforms: [ // TODO: Update the platforms your plugin supports. // If your plugin only supports iOS, remove `.macOS(...)`. // If your plugin only supports macOS, remove `.iOS(...)`. .iOS("13.0"), .macOS("10.15") ], products: [ // TODO: Update your library and target names. // If the plugin name contains "_", replace with "-" for the library name .library(name: "plugin-name", targets: ["plugin_name"]) ], dependencies: [], targets: [ .target( // TODO: Update your target name. name: "plugin_name", dependencies: [], resources: [ // TODO: If your plugin requires a privacy manifest // (e.g. if it uses any required reason APIs), update the PrivacyInfo.xcprivacy file // to describe your plugin's privacy impact, and then uncomment this line. // For more information, see: // https://developer.apple.com/documentation/bundleresources/privacy_manifest_files // .process("PrivacyInfo.xcprivacy"), // TODO: If you have other resources that need to be bundled with your plugin, refer to // the following instructions to add them: // https://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package ], cSettings: [ // TODO: Update your plugin name. .headerSearchPath("include/plugin_name") ] ) ] ) -
更新
Package.swift文件中的受支持平台。Package.swiftswiftplatforms: [ // TODO: Update the platforms your plugin supports. // If your plugin only supports iOS, remove `.macOS(...)`. // If your plugin only supports macOS, remove `.iOS(...)`. .iOS("13.0"), .macOS("10.15") ], -
更新
Package.swift文件中的包、库和目标名称。Package.swiftswiftlet package = Package( // TODO: Update your plugin name. name: "plugin_name", platforms: [ .iOS("13.0"), .macOS("10.15") ], products: [ // TODO: Update your library and target names. // If the plugin name contains "_", replace with "-" for the library name .library(name: "plugin-name", targets: ["plugin_name"]) ], dependencies: [], targets: [ .target( // TODO: Update your target name. name: "plugin_name", dependencies: [], resources: [ // TODO: If your plugin requires a privacy manifest // (e.g. if it uses any required reason APIs), update the PrivacyInfo.xcprivacy file // to describe your plugin's privacy impact, and then uncomment this line. // For more information, see: // https://developer.apple.com/documentation/bundleresources/privacy_manifest_files // .process("PrivacyInfo.xcprivacy"), // TODO: If you have other resources that need to be bundled with your plugin, refer to // the following instructions to add them: // https://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package ], cSettings: [ // TODO: Update your plugin name. .headerSearchPath("include/plugin_name") ] ) ] ) -
如果你的插件有
PrivacyInfo.xcprivacy文件,请将其移动到ios/plugin_name/Sources/plugin_name/PrivacyInfo.xcprivacy,并取消注释Package.swift文件中的资源配置。Package.swiftswiftresources: [ // TODO: If your plugin requires a privacy manifest // (e.g. if it uses any required reason APIs), update the PrivacyInfo.xcprivacy file // to describe your plugin's privacy impact, and then uncomment this line. // For more information, see: // https://developer.apple.com/documentation/bundleresources/privacy_manifest_files .process("PrivacyInfo.xcprivacy"), // TODO: If you have other resources that need to be bundled with your plugin, refer to // the following instructions to add them: // https://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package ], -
将任何资源文件从
ios/Assets移动到ios/plugin_name/Sources/plugin_name(或其子目录)。如有必要,将这些资源文件添加到你的Package.swift文件中。更多说明,请参阅 https://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package。 -
将所有公共头文件从
ios/Classes移动到ios/plugin_name/Sources/plugin_name/include/plugin_name。如果你不确定哪些头文件是公共的,请检查你的
podspec文件中的public_header_files属性。如果未指定此属性,则默认所有头文件均为公共的。你应该考虑是否希望所有头文件都公开。在
pubspec.yaml文件中定义的pluginClass必须是公共的,并位于此目录中。
-
处理
modulemap。如果你的插件没有
modulemap,请跳过此步骤。如果你为了创建一个 Test 子模块而使用了 CocoaPods 的
modulemap,请考虑在 Swift Package Manager 中将其移除。注意,这会使所有公共头文件都可通过该模块访问。若要从 Swift Package Manager 移除
modulemap但保留在 CocoaPods 中,请在插件的Package.swift文件中排除modulemap和伞形头文件。下面的示例假设
modulemap和伞形头文件位于ios/plugin_name/Sources/plugin_name/include目录中。Package.swiftswift.target( name: "plugin_name", dependencies: [], exclude: ["include/cocoapods_plugin_name.modulemap", "include/plugin_name-umbrella.h"],如果你希望保持单元测试与 CocoaPods 和 Swift Package Manager 的双重兼容,可以尝试以下方法:
Tests/TestFile.mobjc@import plugin_name; @import plugin_name.Test; #if __has_include(<plugin_name/plugin_name-umbrella.h>) @import plugin_name.Test; #endif如果你想在 Swift 包中使用自定义
modulemap,请参考 Swift Package Manager 的官方文档。 -
将所有剩余文件从
ios/Classes移动到ios/plugin_name/Sources/plugin_name。 -
ios/Assets、ios/Resources和ios/Classes目录现在应该是空的,可以删除。 -
如果你的头文件不再与实现文件在同一个目录中,你需要更新导入语句。
例如,假设进行了以下迁移:
之前
ios/Classes/ ├── PublicHeaderFile.h └── ImplementationFile.m之后
ios/plugin_name/Sources/plugin_name/ └── include/plugin_name/ └── PublicHeaderFile.h └── ImplementationFile.m
在此示例中,
ImplementationFile.m中的导入语句应更新为:Sources/plugin_name/ImplementationFile.mobjc#import "PublicHeaderFile.h" #import "./include/plugin_name/PublicHeaderFile.h" -
如果你的插件使用了 Pigeon,请更新你的 Pigeon 输入文件。
pigeons/messages.dartdartjavaOptions: JavaOptions(), objcHeaderOut: 'ios/Classes/messages.g.h', objcSourceOut: 'ios/Classes/messages.g.m', objcHeaderOut: 'ios/plugin_name/Sources/plugin_name/messages.g.h', objcSourceOut: 'ios/plugin_name/Sources/plugin_name/messages.g.m', copyrightHeader: 'pigeons/copyright.txt',如果你的
objcHeaderOut文件不再与objcSourceOut位于同一目录,你可以使用ObjcOptions.headerIncludePath来更改#import。pigeons/messages.dartdartjavaOptions: JavaOptions(), objcHeaderOut: 'ios/Classes/messages.g.h', objcSourceOut: 'ios/Classes/messages.g.m', objcHeaderOut: 'ios/plugin_name/Sources/plugin_name/include/plugin_name/messages.g.h', objcSourceOut: 'ios/plugin_name/Sources/plugin_name/messages.g.m', objcOptions: ObjcOptions( headerIncludePath: './include/plugin_name/messages.g.h', ), copyrightHeader: 'pigeons/copyright.txt',运行 Pigeon 以使用最新配置重新生成代码。
-
使用你可能需要的任何自定义设置更新你的
Package.swift文件。在 Xcode 中打开
ios/plugin_name/目录。在 Xcode 中打开你的
Package.swift文件。确认 Xcode 没有为此文件产生任何警告或错误。如果你的
ios/plugin_name.podspec文件包含 CocoaPodsdependency,请将相应的 Swift Package Manager 依赖项添加到你的Package.swift文件中。如果你的包必须显式链接为
static或dynamic(Apple 不推荐),请更新 Product 以定义其类型。Package.swiftswiftproducts: [ .library(name: "plugin-name", type: .static, targets: ["plugin_name"]) ],进行其他自定义。有关如何编写
Package.swift文件的更多信息,请参阅 https://developer.apple.com/documentation/packagedescription。
-
更新你的
ios/plugin_name.podspec以指向新路径。ios/plugin_name.podspecrubys.source_files = 'Classes/**/*.{h,m}' s.public_header_files = 'Classes/**/*.h' s.module_map = 'Classes/cocoapods_plugin_name.modulemap' s.resource_bundles = {'plugin_name_privacy' => ['Resources/PrivacyInfo.xcprivacy']} s.source_files = 'plugin_name/Sources/plugin_name/**/*.{h,m}' s.public_header_files = 'plugin_name/Sources/plugin_name/include/**/*.h' s.module_map = 'plugin_name/Sources/plugin_name/include/cocoapods_plugin_name.modulemap' s.resource_bundles = {'plugin_name_privacy' => ['plugin_name/Sources/plugin_name/PrivacyInfo.xcprivacy']} -
更新从 Bundle 加载资源的方式,使用
SWIFTPM_MODULE_BUNDLE。objc#if SWIFT_PACKAGE NSBundle *bundle = SWIFTPM_MODULE_BUNDLE; #else NSBundle *bundle = [NSBundle bundleForClass:[self class]]; #endif NSURL *imageURL = [bundle URLForResource:@"image" withExtension:@"jpg"]; -
如果你的
ios/plugin_name/Sources/plugin_name/include目录仅包含一个.gitkeep,你需要更新你的.gitignore以包含以下内容:.gitignore!.gitkeep运行
flutter pub publish --dry-run以确保include目录被正确发布。 将插件的更改提交到你的版本控制系统。
-
验证插件在使用 CocoaPods 时仍然可以正常工作。
关闭 Swift Package Manager
shflutter config --no-enable-swift-package-manager导航到插件的示例应用。
shcd path/to/plugin/example/确保插件的示例应用可以构建和运行。
shflutter run导航到插件的顶层目录。
shcd path/to/plugin/运行 CocoaPods 验证检查
shpod lib lint ios/plugin_name.podspec --configuration=Debug --skip-tests --use-modular-headers --use-librariesshpod lib lint ios/plugin_name.podspec --configuration=Debug --skip-tests --use-modular-headers
-
验证插件在使用 Swift Package Manager 时可以正常工作。
开启 Swift Package Manager
shflutter config --enable-swift-package-manager导航到插件的示例应用。
shcd path/to/plugin/example/确保插件的示例应用可以构建和运行。
shflutter run在 Xcode 中打开插件的示例应用。确保 Package Dependencies 显示在左侧的 Project Navigator 中。
-
验证测试通过。
如果你的插件有原生单元测试 (XCTest),请确保同时也更新了插件示例应用中的单元测试。
遵循测试插件的说明。
(可选,但推荐)将插件作为本地包添加到示例应用中
#如果你的插件包含示例,建议将插件作为本地包添加到示例应用中。这不是必需的,但在示例应用中编辑插件源代码时,它能提供更好的 Xcode 支持。参见 issue #179032。
将插件添加为本地包
#在终端中导航到
my_plugin。-
运行以下命令在 Xcode 中打开示例应用的工作区(如果你的插件针对 macOS,请将
ios替换为macos):
open example/ios/Runner.xcworkspace
-
右键点击 Flutter > Add Files to “Runner”。

-
选择
my_plugin/ios/my_plugin(或根据你的插件支持的平台选择macos或darwin)。 -
确保选中“Reference files in place”(通常是默认选项),然后点击 Finish。

这会将插件添加为本地包,但它会以绝对路径引用,这对于发布是不利的。要将其更改为相对路径,请执行以下步骤。
修改为相对路径
#-
在 File Inspector 中复制插件的“Full Path”。

-
在终端中:
open -a Xcode example/ios/Runner.xcodeproj/project.pbxproj -
查找以下内容:
path = [COPIED FULL PATH]; sourceTree = "<absolute>"例如
path = /Users/username/path/to/my_plugin/ios/my_plugin; sourceTree = "<absolute>" -
并替换为相对路径:
path = ../../ios/my_plugin; sourceTree = "<group>"(根据需要将
ios调整为macos或darwin)。
如何更新插件示例应用中的单元测试
#如果你的插件有原生 XCTests,并且满足以下任一条件,你可能需要更新它们以适配 Swift Package Manager:
- 你为测试使用了 CocoaPod 依赖项。
- 你的插件在
Package.swift文件中被显式设置为type: .dynamic。
要更新你的单元测试:
在 Xcode 中打开你的
example/ios/Runner.xcworkspace。-
如果你之前为测试使用了 CocoaPod 依赖项(例如
OCMock),你需要从你的Podfile文件中将其移除。ios/Podfilerubytarget 'RunnerTests' do inherit! :search_paths pod 'OCMock', '3.5' end然后在终端中,于
plugin_name_ios/example/ios目录下运行pod install。 -
导航到项目的 Package Dependencies。

项目的包依赖项
-
点击 + 按钮,通过在右上角的搜索栏中搜索,添加任何仅限测试的依赖项。

搜索仅限测试的依赖项
-
确保将该依赖项添加到
RunnerTests目标中。
确保将该依赖项添加到
RunnerTests目标 点击 Add Package 按钮。
-
如果你在
Package.swift文件中显式将插件库类型设置为.dynamic(Apple 不推荐),你也需要将其添加为RunnerTests目标的依赖项。确保
RunnerTests的 Build Phases 中有 Link Binary With Libraries 构建阶段
RunnerTests目标中的Link Binary With Libraries构建阶段如果构建阶段不存在,请创建一个。点击 add 按钮,然后点击 New Link Binary With Libraries Phase。

添加
Link Binary With Libraries构建阶段导航到项目的 Package Dependencies。
点击 add 按钮。
在弹出的对话框中,点击 Add Local... 按钮。
导航到
plugin_name/plugin_name_ios/ios/plugin_name_ios并点击 Add Package 按钮。确保将其添加到
RunnerTests目标,并点击 Add Package 按钮。
确保通过 Product > Test 测试通过。