Swift 包管理器:创建自定义框架
Swift package manager: create custom framework
我想在 Swift 中创建一个自定义框架,以便我可以在多个项目中使用它。因此我从
开始
mkdir TestFramework && cd TestFramework
swift package init --type library
和
swift package generate-xcodeproj
然后我开始在那里创建一些 类 并构建代码。结果是一个 .framework
文件。我将它移动到我的其他项目并将其链接到那里(因此我只是将 .framework-folder 复制到 Xcode-project 并将其添加到目标)。 import TestFramework
有效,但我无权访问任何 类,我在框架中创建:Use of unresolved identifier 'TestClass'
奇怪的是:TestFramework.framework/Versions/A/TestFramework
好像是可执行文件。这是 Package.swift:
let package = Package(
name: "TestFramework",
products: [
// Products define the executables and libraries produced by a package, and make them visible to other packages.
.library(
name: "TestFramework",
targets: ["TestFramework"]),
],
解决此问题的最佳方法是使用 Xcode 顶级工作区(文件 -> 新建 -> 工作区)。因此,创建一个名为 Example.
的工作区
作为第二步,创建一个名为 lib 的目录并将其放在 Example 目录中。将它放在目录中并不是严格要求的,但我这样做是为了将文件保存在一个项目目录中。 lib
目录中的下一个 运行:
swift package init --type library
并添加一些代码来创建您的框架。
接下来使用 Xcode 创建一个新项目。所以 File -> New -> Project 并将该项目也存储在 Example 目录中(同样不严格要求将其放在 Example 中)。现在让我们假设您创建了一个名为 TestUI 的 Cocoa 应用程序。
现在打开示例工作区并使用文件 -> 添加文件到 "Example" 将两个项目添加到工作区。您应该为 lib
目录添加生成的 lib.xcodeproj
,为 TestUI 添加 TestUI.xcodeproj
。
从这一刻起 Xcode 将自动处理事情。它将两个项目的所有文件存储在一个构建目录中,您可以 create/run/build/debug 您的应用程序,正如您所期望的那样。
结构应如下所示:
Example
|-- Example.xcworkspace
|-- TestUI
| |-- TestUI
| | |-- AppDelegate.swift
| | |-- Assets.xcassets
| | | |-- AppIcon.appiconset
| | | | `-- Contents.json
| | | `-- Contents.json
| | |-- Base.lproj
| | | `-- Main.storyboard
| | |-- Info.plist
| | |-- MailboxViewController.swift
| | |-- TestUI.entitlements
| | `-- ViewController.swift
| `-- TestUI.xcodeproj
`-- lib
|-- lib.xcodeproj
|-- Package.resolved
|-- Package.swift
|-- README.md
|-- Sources
| |-- ExampleLib
| | |-- Account.swift
| | |-- Credentials.swift
这种方法有一个主要限制。如果您的图书馆没有 Swift 组件,例如一个 C 库的包装器,它不会开箱即用。如果您尝试使用它,您将收到类似 "Cannot find required Framework xxx" 的消息。如果您向库中添加一些基于 'C' 的必需包,也会发生这种情况。
我发现了以下解决方法。首先进入lib
目录和运行以下命令:
find lib.xcodeproj -name module.modulemap
如果您有 used/created xxx
库,您将得到以下输出:
lib.xcodeproj/GeneratedModuleMap/xxx/module.modulemap
现在转到 Example 工作区和 select TestUI -> Build Settings -> All 并在搜索框中输入 "Other Swift Flags"。
打开它并添加以下两个字段:
-Xcc
-fmodule-map-file=$(SRCROOT)/../lib/lib.xcodeproj/GeneratedModuleMap/xxx/module.modulemap
就是这样。现在应该一切正常了。对于编译和 运行ning,甚至没有必要在 TestUI 应用程序中嵌入二进制文件,尽管我认为它对于分发是必要的。
确保您的 类 和其他类型是 public
,包括方法和初始值设定项。
在框架上工作时,避免在单元测试中使用 testable
有助于测试 public 接口,因为消费应用程序会看到它。
我想在 Swift 中创建一个自定义框架,以便我可以在多个项目中使用它。因此我从
开始mkdir TestFramework && cd TestFramework
swift package init --type library
和
swift package generate-xcodeproj
然后我开始在那里创建一些 类 并构建代码。结果是一个 .framework
文件。我将它移动到我的其他项目并将其链接到那里(因此我只是将 .framework-folder 复制到 Xcode-project 并将其添加到目标)。 import TestFramework
有效,但我无权访问任何 类,我在框架中创建:Use of unresolved identifier 'TestClass'
奇怪的是:TestFramework.framework/Versions/A/TestFramework
好像是可执行文件。这是 Package.swift:
let package = Package(
name: "TestFramework",
products: [
// Products define the executables and libraries produced by a package, and make them visible to other packages.
.library(
name: "TestFramework",
targets: ["TestFramework"]),
],
解决此问题的最佳方法是使用 Xcode 顶级工作区(文件 -> 新建 -> 工作区)。因此,创建一个名为 Example.
的工作区作为第二步,创建一个名为 lib 的目录并将其放在 Example 目录中。将它放在目录中并不是严格要求的,但我这样做是为了将文件保存在一个项目目录中。 lib
目录中的下一个 运行:
swift package init --type library
并添加一些代码来创建您的框架。
接下来使用 Xcode 创建一个新项目。所以 File -> New -> Project 并将该项目也存储在 Example 目录中(同样不严格要求将其放在 Example 中)。现在让我们假设您创建了一个名为 TestUI 的 Cocoa 应用程序。
现在打开示例工作区并使用文件 -> 添加文件到 "Example" 将两个项目添加到工作区。您应该为 lib
目录添加生成的 lib.xcodeproj
,为 TestUI 添加 TestUI.xcodeproj
。
从这一刻起 Xcode 将自动处理事情。它将两个项目的所有文件存储在一个构建目录中,您可以 create/run/build/debug 您的应用程序,正如您所期望的那样。
结构应如下所示:
Example
|-- Example.xcworkspace
|-- TestUI
| |-- TestUI
| | |-- AppDelegate.swift
| | |-- Assets.xcassets
| | | |-- AppIcon.appiconset
| | | | `-- Contents.json
| | | `-- Contents.json
| | |-- Base.lproj
| | | `-- Main.storyboard
| | |-- Info.plist
| | |-- MailboxViewController.swift
| | |-- TestUI.entitlements
| | `-- ViewController.swift
| `-- TestUI.xcodeproj
`-- lib
|-- lib.xcodeproj
|-- Package.resolved
|-- Package.swift
|-- README.md
|-- Sources
| |-- ExampleLib
| | |-- Account.swift
| | |-- Credentials.swift
这种方法有一个主要限制。如果您的图书馆没有 Swift 组件,例如一个 C 库的包装器,它不会开箱即用。如果您尝试使用它,您将收到类似 "Cannot find required Framework xxx" 的消息。如果您向库中添加一些基于 'C' 的必需包,也会发生这种情况。
我发现了以下解决方法。首先进入lib
目录和运行以下命令:
find lib.xcodeproj -name module.modulemap
如果您有 used/created xxx
库,您将得到以下输出:
lib.xcodeproj/GeneratedModuleMap/xxx/module.modulemap
现在转到 Example 工作区和 select TestUI -> Build Settings -> All 并在搜索框中输入 "Other Swift Flags"。
打开它并添加以下两个字段:
-Xcc
-fmodule-map-file=$(SRCROOT)/../lib/lib.xcodeproj/GeneratedModuleMap/xxx/module.modulemap
就是这样。现在应该一切正常了。对于编译和 运行ning,甚至没有必要在 TestUI 应用程序中嵌入二进制文件,尽管我认为它对于分发是必要的。
确保您的 类 和其他类型是 public
,包括方法和初始值设定项。
在框架上工作时,避免在单元测试中使用 testable
有助于测试 public 接口,因为消费应用程序会看到它。