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 接口,因为消费应用程序会看到它。