码迷,mamicode.com
首页 > 编程语言 > 详细

Swift 包管理器教程

时间:2017-05-05 11:45:03      阅读:341      评论:0      收藏:0      [点我收藏+]

标签:工作原理   方法   依赖   des   开始   运行   结构   生态   country   

原文:An Introduction to the Swift Package Manager
作者: Mikael Konutgan
译者:kmyhy

Swift 包管理器的正式发布是随着 Swift3.0 一起发布的,它是一个用于构建能够运行在 macOS 和 Linux 上的 Swift 库和 app 的新方法。它能够帮助你管理依赖,让你轻松构建、测试和运行你的 Swift 代码。

Swift 包管理器有助于极大地改进 Swift 生态系统,让 Swift 更容易使用、部署到没有 Xcode 的平台上,比如 Linux。Swift 包管理器还能解决在使用多个相互依赖的库时的“依赖地狱”的问题。

重要的一点是,因为 Swift 3 的原因,Swift 包管理器只能在 host 平台上编译。换句话说,你无法编译、使用 iOS、watchOS 和 tvOS 上的包。

让我们开始吧!

开始

在开始之前,确认你已经安装了 Swift 3.0 以上。Swift 3 内置在 Xcode8+,因此如果你已经安装了 Xcode8 或以上,你就可以开始本教程。当然实际上你并不需要用 Xcode 去完成本教程,你可以直接从 swift.org 下载安装 Swift 3。

打开终端窗口,输入 swift package。你会看到这个命令的介绍。你将使用这几个命令:

  1. swift package init ,创建新包
  2. swift package update ,更新一个包的依赖
  3. swift package generate-xcodeproj ,为包生成 Xcode 项目

要学习 Swift 包管理器,我们将编写一个命令行 app,用一个库打印出所有国家的国旗字符。首先我们会创建一个可执行包。这种包也就是命令行 app。Swift web app 也属于这种类别。

通过以下命令,创建一个名为 Flag 的可执行包:

mkdir Flag
cd Flag
swift package init --type executable

在运行 swift package init 命令行时,切换到 Flag 目录是关键的,因为 Flag 将作为包名。你会看到输出中会显示一些文件和文件夹,它们是自动生成的。现在来熟悉一下项目结构:

技术分享https://koenig-media.raywenderlich.com/uploads/2016/12/Flag-%E2%94%9C%E2%94%80%E2%94%80-Package.swi_.png’ width= ‘300’/>

  1. Package.swift 包含包的描述信息,还包含包的依赖。
  2. Sources/,如名称所示,用于存放你的 Swift 源文件。里面会生成一个 main.swift 文件。这是应用程序的入口。现在,它只会打印 hello world。
  3. Tests/ ,包含单元测试,你可以用 XCText 编写这些测试。待会你会写测试代码。

回到终端窗口,运行:

swift build

这会编译包并在 .build/debug/ 创建一个可执行文件 Flag。运行这个 app,只需要:

.build/debug/Flag

你会在屏幕上看到 Hello,world!

恭喜你!你创建和编译通过了你的第一个 Swift 包!

创建库

要真正能够生成某个国家的国企字符,我们需要编写一个名为 Atlas 的库。然后在你的 Flag app 中调用这个库。

切到 Flag 包之外的目录,通过终端命令创建一个库:

cd ..
mkdir Atlas
cd Atlas
swift package init --type library

包管理器会创建几个文件和文件夹。

技术分享https://koenig-media.raywenderlich.com/uploads/2017/01/atlas-library-structure.png’ width=’300’/>

这次,main.swift 会被 Atlas.swift 所替代。这个文件以及在 Sources/ 目录下的文件都会被导入到这个库中。实际上,库和可执行包的区别就在于有没有 main.swift。

这次我们需要用一个测试。用 swift test 来运行这个测试。Swift 包管理器会编译库并运行测试。

注意:你会在 Tests/ 目录下看到 LinuxMain.swift 文件,在 AtlasTests 的测试案例类中还有一个 allTests 属性。对于要在 Linux 上运行 XCTest 测试而言,这两者都是必须的。Linux 没有 O-C 运行时,而 O-C 运行时会自动查找以 test 开头的方法并运行它。每当添加一个测试方法,你都需要修改这个 allTests 属性,每当添加一个新的测试案例类,你都需要修改 LinuxMain.swift。

打开 Atlas.swift 修改内容为:

public struct Country {
  public let code: String

  public init(code: String) {
    self.code = code.uppercased()
  }

  public var emojiFlag: String {
    return "\u{1f1f5}\u{1f1f7}"
  }
}

这里我们实现了一个 Country 结构,它通过一个 ISO 国别代码进行初始化。emojiFlag 属性根据国别代码返回对应的国旗字符。现在,你需要编写测试。

注意每个方法和属性都标记为公有的,这样它的每个成员对于使用这个库的代码来说都是课件的:]

打开 AtlasTests.swift,编辑内容为:

import XCTest
@testable import Atlas

class AtlasTests: XCTestCase {
  func testAustria() {
    XCTAssertEqual(Country(code: "AT").emojiFlag, "\u{1f1e6}\u{1f1f9}")
  }

  func testTurkey() {
    XCTAssertEqual(Country(code: "TR").emojiFlag, "\u{1f1f9}\u{1f1f7}")
  }

  func testUnitedStates() {
    XCTAssertEqual(Country(code: "US").emojiFlag, "\u{1f1fa}\u{1f1f8}")
  }
}

extension AtlasTests {
  static var allTests : [(String, (AtlasTests) -> () throws -> Void)] {
    return [
      ("testAustria", testAustria),
      ("testTurkey", testTurkey),
      ("testUnitedStates", testUnitedStates)
    ]
  }
}

这里实现了 3 个测试。我们创建了 3 个不同的国籍,然后断言它们是否拥有正确的 emoji 国旗字符。

运行测试:

swift test

你会看到 3 个测试被运行,但全部失败。这说明我们还有很多事情要干啊 :]

现在我们测试失败了,我们要让它们通过测试。

emoji 国旗的工作原理非常简单:传入一个国家代码,比如 AT,然后将每个字符转换成设为的地区指示标志。例如, ?? 和 ??。然后将二者组合在一起,你就会得到 emoji 国旗!

技术分享https://koenig-media.raywenderlich.com/uploads/2017/01/ragecomic_flags.png’ width=’600’/>

回到 Atlas.swift 为 Country 结构增加一个方法:

func regionalIndicatorSymbol(unicodeScalar: UnicodeScalar) -> UnicodeScalar? {
  let uppercaseA = UnicodeScalar("A")!
  let regionalIndicatorSymbolA = UnicodeScalar("\u{1f1e6}")!
  let distance = unicodeScalar.value - uppercaseA.value
  return UnicodeScalar(regionalIndicatorSymbolA.value + distance)
}

这里,我们利用了字母和区域指示标志在 Unicode 表中的值都是连续排列的原理。比如 A 是 65,B 是 66,而 ?? 是 127462,?? 就是 127463。如果将字符 P 转换成区域指示标志,需要计算出 A 到 P 的值相差多少,然后将 ??加上这个差值就得到 ??。

这是最难的部分。写好这个方法后,剩下的事情就简单了。将 emojiFlag 属性定义修改为:

public var emojiFlag: String {
  return code.unicodeScalars.map { 
  String(regionalIndicatorSymbol(unicodeScalar: $0)!) } .joined()
}

我们将国家代码的每个字母放到数组中,然后将每个字母转换成对应的区域指示标志,然后将它们连在一起。这就得到了国旗!

运行测试,3 个测试都通过了。

接下来将代码提交到 Git,并标记一个本号。因为这是我们的第一个版本,我们可以将版本标记为 1.0.0。

执行下列命令,创建 Git 存储库并标记版本:

git init
git add .
git commit -m "Initial commit"
git tag 1.0.0

创建可执行包

现在你已经准备好 Flag 库,我们可以将它添加为 Flag 可执行包的依赖。

回到 Flag 目录,打开 Package.swift 文件。它目前是这个样子:

import PackageDescription

let package = Package(
  name: "Flag"
)

每个 Swift 包都有一个类似的 PackageDescription。最重要的参数是 dependencies 参数。

将包描述修改为这样:

let package = Package(
  name: "Flag",
  dependencies: [
    .Package(url: "../Atlas", "1.0.0")
  ]
)

这里,我们声明 Flag 包拥有一个依赖,这个依赖的 URL 是 ../Atlas,版本是 1.0.0。

版本号应该使用语义上的版本号。简单说,就是类似于 MAJOR.MINOR.PATCH 这样的版本号。MAJOR 版本表示的是不向后兼容的修改,MINOR 版本表示向后兼容的修改,PATCH 版本是 bug 的修复。关于语义版本,细节可参考 这里

大部分情况下,你只想让新版本在 bug 修复和小版本改进上做修改。幸好,Swift 包管理器允许我们这样做。将包描述修改为:

let package = Package(
  name: "Flag",
  dependencies: [
    .Package(url: "../Atlas", majorVersion: 1)
  ]
)

包管理器提供了你在更新库时想精确控制的版本。请参考这里

编译包:

swift build

Swift 包管理器将抓取、编译库并将之连接到你的可执行包。现在的文件夹结构将是这个样子:

技术分享https://koenig-media.raywenderlich.com/uploads/2017/01/flag-structure.png’ width=’300’/>

你会看到 Swift 包管理器已经细心地根据你的要求将 1.0.0 版本安装到项目中了。打开 main.swift 文件,编辑内容如下:

import Atlas

let arguments = CommandLine.arguments

if arguments.count != 2 {
  print("USAGE: flag [iso country code]")
} else {
  let code = arguments[1]
  let country = Atlas.Country(code: code)
  print(country.emojiFlag)
}

这里,我们导入了 Atlas 库,根据命令行参数的第一个参数,打印出对应的国旗 emoji。如果缺少参数,我们会打印命令帮助。

编译运行 app:

swift build
./.build/debug/Flag US

你在终端窗口中看到了美国国旗!

在你和你的 app 玩得不亦乐乎的时候,我们该来打包它 了。最后编译一下 app,这次需要加上 release 优化参数:

swift build --configuration release

现在你可以这样运行你的 release 版 app 了:

./.build/release/Flag PR

你可以将 ./.build/release/Flag 文件打包压缩,然后分享给你的朋友、家人或其它人了 :]

用包管理器生成 Xcode 项目

老旧的命令行和文本编辑器很酷,但你可能是一个 iOS 或 macOS 程序员,你使用的是 Xcode。别担心——大部分工作 Xcode 都可以做得很好。

回到 Atlas 包下面,生成一个 Xcode 项目:

cd ../Atlas
swift package generate-xcodeproj

这会生成一个 Atlas.xcodeproj 文件。你可以用 Xcode 打开这个项目,像其他 Xcode 项目一样编译包和运行测试。

技术分享https://koenig-media.raywenderlich.com/uploads/2017/01/xcode-650x357.png’ width= ‘600’/>

同样的方法可以用在 Flag 包上。在 Flag 文件夹下面执行 swift package generate-xcodeproj 命令,生成 Flag.xcodeproj。

cd ../Flag
swift package generate-xcodeproj

用 Xcode 打开项目,确认 Flag 可执行目标是否选中,它显示一个小的终端窗口的图标。现在你也可以编译和运行这个包了。

为了指定可执行命令的参数,请进入 Product\Scheme\Edit Scheme… 窗口,选择 Run\Arguments ,在 Arguments Passed On Launch 中添加一个参数比如 US:

技术分享https://koenig-media.raywenderlich.com/uploads/2017/01/Flag_xcodeproj-650x361.png’ width=’600’/>

注意,Xcode 无法添加和编译依赖,因此你无法完全离开命令行。

结束

你可以从这里下载完成的 Swift 包管理器项目。

你还可以参考Swift 官网关于包管理器的章节

关于包描述选项的最新文档,请参考github

关于 Swift 4 的包管理器修改方向,你可以参考 Swift 演进路线图的邮件列表

你还可以参考IBM 的 Swift Package Catalog,它可以帮助你找到可以用在你项目中的新包。

在 Swift 包管理器能够支持非主机平台之前,你仍然不得不使用 Cocoapods 或 Carthage 来构建 iOS、watchOS 和 tvOS app。

留作今天的作业,你可以将你的库推到 GitHub,然后在 Atlas 中使用它的远程依赖。提示:只需要将 dependency 的 url 参数修改为 GitHub URL。

尝试添加新的功能,比如当没有提供任何参数时,列出所有国家的名字和国旗。提示:你将需要用到 Locale.isoRegionCodes。

在 Atlas 库中实现你的新功能,然后创建新的版本,比如 1.1.0,然后在 Flag 中使用这个新版本。确认你在包描述中使用了新版本,然后通过 Swift 包管理器将依赖升级到新版本。

将你的答案公布到下面的留言中,祝你开心!

Swift 包管理器教程

标签:工作原理   方法   依赖   des   开始   运行   结构   生态   country   

原文地址:http://blog.csdn.net/kmyhy/article/details/71190915

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!