构建一个库

本指南的源代码可以在 GitHub 上找到

安装 Swift

要开始您的 Swift 之旅,请先安装 Swift,您可以在 macOSLinuxWindows 上使用它。

提示:要测试 Swift 是否安装成功,请在终端或命令行中运行 swift --version

Swift 自带Swift 包管理器 (SwiftPM),用于管理 Swift 代码的分发。它让您能够轻松地将其他 Swift 包导入到您的应用程序和库中,是每个 Swift 开发者的重要工具。

Swift 采用 Apache License, Version 2.0 许可证。

初始化项目

让我们用我们的新 Swift 开发环境编写一个小型库。 首先,我们将使用 SwiftPM 为我们创建一个新项目。在你选择的终端中运行:

$ mkdir MyLibrary
$ cd MyLibrary
$ swift package init --name MyLibrary --type library

这将生成一个名为 MyLibrary 的新目录,包含以下文件:

.
├── Package.swift
├── Sources
│   └── MyLibrary
│       └── MyLibrary.swift
└── Tests
    └── MyLibraryTests
        └── MyLibraryTests.swift

Package.swift 是 Swift 的清单文件。它用于保存项目的元数据和依赖项。

Sources/MyLibrary/MyLibrary.swift 是库的初始源文件,我们将在这里编写库代码。 Test/MyLibraryTests/MyLibraryTests.swift 是我们可以为库编写测试的地方。

实际上,SwiftPM 为我们生成了一个”Hello, world!”项目,包括一些单元测试! 我们可以在终端中运行 swift test 来运行测试。

$ swift test
Building for debugging...
[5/5] Linking MyLibraryPackageTests
Build complete! (7.91s)
Test Suite 'All tests' started at 2023-08-29 18:59:31.328
Test Suite 'MyLibraryPackageTests.xctest' started at 2023-08-29 18:59:31.329
Test Suite 'MyLibraryTests' started at 2023-08-29 18:59:31.329
Test Case '-[MyLibraryTests.MyLibraryTests testExample]' started.
Test Case '-[MyLibraryTests.MyLibraryTests testExample]' passed (0.001 seconds).
Test Suite 'MyLibraryTests' passed at 2023-08-29 18:59:31.330.
	 Executed 1 test, with 0 failures (0 unexpected) in 0.001 (0.001) seconds
Test Suite 'MyLibraryPackageTests.xctest' passed at 2023-08-29 18:59:31.330.
	 Executed 1 test, with 0 failures (0 unexpected) in 0.001 (0.001) seconds
Test Suite 'All tests' passed at 2023-08-29 18:59:31.330.
	 Executed 1 test, with 0 failures (0 unexpected) in 0.001 (0.002) seconds

一个小型库

现在让我们编写一个小型库。 用以下代码替换 MyLibrary.swift 中的示例内容:

import Foundation

struct Email: CustomStringConvertible {
  var description: String

  public init(_ emailString: String) throws {
    let regex = #"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,64}"#
    guard let _ = emailString.range(of: regex, options: .regularExpression) else {
      throw InvalidEmailError(email: emailString)
    }
    self.description = emailString
  }
}

private struct InvalidEmailError: Error {
  let email: String
}

现在让我们为这个强类型的 Email API 添加一个单元测试。 用以下代码替换 MyLibraryTests.swift 中的示例内容:

@testable import MyLibrary
import XCTest

final class MyLibraryTests: XCTestCase {
  func testEmail() throws {
    let email = try Email("[email protected]")
    XCTAssertEqual(email.description, "[email protected]")

    XCTAssertThrowsError(try Email("invalid"))
  }
}

保存后,我们可以再次运行测试:

❯ swift test
Building for debugging...
[5/5] Linking MyLibraryPackageTests
Build complete! (3.09s)
Test Suite 'All tests' started at 2023-08-29 19:01:08.640
Test Suite 'MyLibraryPackageTests.xctest' started at 2023-08-29 19:01:08.641
Test Suite 'MyLibraryTests' started at 2023-08-29 19:01:08.641
Test Case '-[MyLibraryTests.MyLibraryTests testEmail]' started.
Test Case '-[MyLibraryTests.MyLibraryTests testEmail]' passed (0.002 seconds).
Test Suite 'MyLibraryTests' passed at 2023-08-29 19:01:08.643.
	 Executed 1 test, with 0 failures (0 unexpected) in 0.002 (0.002) seconds
Test Suite 'MyLibraryPackageTests.xctest' passed at 2023-08-29 19:01:08.643.
	 Executed 1 test, with 0 failures (0 unexpected) in 0.002 (0.002) seconds
Test Suite 'All tests' passed at 2023-08-29 19:01:08.643.
	 Executed 1 test, with 0 failures (0 unexpected) in 0.002 (0.003) seconds

本指南的源代码可以在 GitHub 上找到