Swift Package Manager 详细使用(2018-10-14更新)

Swift Package Manager (SwiftPM) 是 Apple 推出的一个包管理工具, 用于创建, 使用 Swift 的库, 以及可执行程序的工具.

使用方法

1. 基本使用: 创建可执行程序.

    1. 创建目录, 进入目录
$ mkdir executableDemo     
$ cd executableDemo        
    1. 创建一个可执行的包

一共可快捷创建四种类型的包文件, executable 指可执行的二进制包, Library 指静态库包, system-module 指 系统库的包.

$ swift package init --help
OVERVIEW: Initialize a new package

OPTIONS:
  --type   empty|library|executable|system-module
$ swift package init --type executable 

创建完可执行的包后, 我们在 Source 的子目录下可以看见以包名建的一个子目录, 在子目录里会默认生成一个 main.swift 文件, 这是执行 module 的入口.

在 main.swift 中输入以下代码. 代码意思是 如果执行 Module 时带的参数不为 2 , 输出 Usage: hello NAME, 否则调用 sayHello 方法.

if CommandLine.arguments.count != 2 {
    print("Usage: hello NAME")
} else {
    let name = CommandLine.arguments[1]
    sayHello(name: name)
}

在与 main.swift 同目录下创建一个 Greeter.swift 目录, 输入以下代码, 可供调用.

func sayHello(name: String) {
    print("Hello, \(name)!")
}
    1. 运行可执行包
$ swift run   # 输出 Usage: hello NAME 
$ swift run executableDemo "Lucy" # 输出 Hello Lucy

如果不带参数执行, 在 run 后面可不写包名


2. 基本使用: 类似 CocoaPods 和 Carthage 的功能, 作为第三方包管理器.

每次 SwiftPM 创建完包项目后, 都会生成一个 Package.swift 文件, 这里面管理包之间的依赖关系.
以 SwiftyJSON 为例.

import PackageDescription

let package = Package(
    name: "Hello_execute",
    dependencies: [
        .package(url: "https://github.com/SwiftyJSON/SwiftyJSON.git", from: "4.0.0"), 
        //第三方库url和版本号, 版本号可在 Release 版本里面查看
    ],
    targets: [
        .target(
            name: "Hello_execute",
            dependencies: ["SwiftyJSON"]),  //依赖的包名称
        .testTarget(
            name: "Hello_executeTests",
            dependencies: ["Hello_execute"]),
    ]
)
$ swift package init --type executable
创建完包项目后, 编辑依赖

更新依赖, 此时会自动从网上 clone 下支持 SwiftPM 的第三方库
$ swift package update 

编译依赖, 编译完会将第三方库链接到 .build 的文件夹中的可执行文件.
$ swift build 

编译完依赖后, 我们可以做两件事.

  1. 在 main.swift 中输入以下代码, 然后在当前库的主目录下, 直接执行 swift run, 可查看结果.
import SwiftyJSON      //引入模块

let json = JSON(["name":"Jack", "age": 25])
print(json)
  1. 我们可以像 CocoaPods 一样使用第三方库.
    在当前目录下生成 Xcode project 入口文件.
swift package generate-xcodeproj 
image.png

打开我们原来创建的 Xcode 项目, 直接将 Library.xcodeproj 拖入到主项目中.
并且 Link 我们新的第三方库.


image.png

3. 基本使用: 自定义一个库作为其他项目的依赖包

$ mkdir LCLib
$ cd LCLib
$ swift package init    //初始化包,不带参数的话默认是Library

在 Source 的子目录下面找到自动生成的 LCLib.swift 文件, 编辑如下代码.

public struct LCLib {
    var text = "Hello, MyLib!"
    public var num:Int
    public init() {
        num = 2
    }
}

回到 Source 所在目录, 因为 SwiftPM 依赖包必须使用git url和版本号,所以我们需要为我们的库创建一个 git 仓库并提交代码和打 tag.

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

这是提交在本地仓库, 在使用的时候注意指名仓库路径.
编辑依赖.

let package = Package(
    name: "Hello_execute",
    dependencies: [
        .package(url: "https://github.com/SwiftyJSON/SwiftyJSON.git", from: "4.2.0"), //第三方库url和版本号, 版本号可在 Release 版本里面查看
        .package(url: "../LCLib", from: "1.0.0")
        注意: 由于我们的 库 没有 push 到远程仓库, 只在本地, 所以这里指的是本地仓库的相对路径
    ],
    targets: [
        .target(
            name: "Hello_execute",
            dependencies: ["SwiftyJSON", "LCLib"]),  //依赖的包名称
        .testTarget(
            name: "Hello_executeTests",
            dependencies: ["Hello_execute"]),
    ]
)

编辑完依赖, 再次编辑 main.swift 文件

import SwiftyJSON       //引入模块

import LCLib

let json = JSON(["name":"Jack", "age": 25])
print(json)

//自定义库
let lib = LCLib()
print(lib)

最后执行 swift run, 运行过程中会编译代码.


4. 高级应用: 包含上面所有.

我们创建完一个包项目后, 编辑 package.swift 文件

import PackageDescription

let package = Package(
    name: "OC2Swift",
    products: [
        // 自定义库
        .library(
            name: "LCLib",
            targets: ["LCLib"]),
        
        // 可执行文件
        .executable(
            name: "LCOC2Swift",
            targets: ["LCOC2Swift"])
    ],
    dependencies: [
        // 外部依赖
        .package(url: "https://github.com/SwiftyJSON/SwiftyJSON.git", from: "4.2.0"),
    ],
    targets: [
        // 每一个 target 执行所需要的依赖
        .target(
            name: "LCLib",
            dependencies: []),
        .target(
            name: "LCOC2Swift",
            dependencies: ["LCLib", "SwiftyJSON"]),
        
//        
//        .target(
//            name: "OC2Swift",
//            dependencies: []),
//        .testTarget(
//            name: "OC2SwiftTests",
//            dependencies: ["OC2Swift"]),
    ]
)

从上往下看.

  • name 表示 package 的名字
  • product 表示 package 的输出, 在这里具体指自定义的 lib 和 executable 文件, 如果要使用自定义库, 不需要提交到本地仓库, 直接作为 lib 输出就可以了.
  • dependencies 表示外部依赖
  • target 指 目标文件, 在这里的 name 都与实际文件名对应, 也就是说每一个要使用的 文件夹 都要写在这里, 并表明对应的依赖. 下面那张图就是两个 target 对应的两个文件夹

这些东西具体细节可以查看官方文件

image.png

5. 高级应用: 带参数执行程序

在第一部分我们其实展示了如何带参数执行

$ swift run executableDemo "Lucy"

我们可以通过 CommandLine.arguments[1] 来获取到这个参数, 但是如果是多个参数, 这样来处理就比较麻烦.
官方对此提出了一个解决方案, 使用 SwiftPM module.
编辑我们的 package.swift 文件, 添加依赖包 SwiftPM.

let package = Package(
    name: "PackageName",
    dependencies: [
        .package(url: "https://github.com/apple/swift-package-manager.git", from: "0.3.0"),
    ],
    targets: [
        .target(
            name: "Hello_execute",
            dependencies: ["SwiftPM"]),  //依赖的包名称
        .testTarget(
            name: "Hello_executeTests",
            dependencies: ["Hello_execute"]),
    ]
)

这里有几点需要注意.

  • 如果一时找不到 SwiftPM 的 tag, 我们可以把官方项目 clone 下来, 在主目录中执行
$ git tag
refs/tags/0.1.0
refs/tags/0.2.0
refs/tags/0.2.1
refs/tags/0.3.0

就可以查看到官方挂在远端的库文件. 类似上面显示的才是.

  • 添加完依赖后, 在我们的 main.swift 中
import Utility     // 这个才是真正定义参数的工具库

// 定义一个参数解析器
let parser = ArgumentParser(usage: "使用", overview: "将网页转为OC")

// 添加参数规则
// --url 是参数标识, -u 是简写, 
// 参数是 String 类型, 除此以外, 参数还可以是 Int, Bool, 数组等类型
// usage 是使用说明
let urlArg = parser.add(option: "--url", shortName: "-u", 
                        kind: String.self, usage: " -u <url>")

// 创建子解析器
let fileParser = parser.add(subparser: "out", overview: "输出文件")
let fileArg = fileParser.add(positional: "out", kind: String.self,
                            usage: "out <file>")

获取参数并使用

// 获取执行参数, 1和2一样的结果
let arguments = Array(ProcessInfo.processInfo.arguments.dropFirst())
// let arguments2 = Array(CommandLine.arguments.dropFirst())

// 解析参数
let result = try parser.parse(arguments)

// 获取参数
let url = result.get(urlArg) ?? "Null"

print("url: \(url))

拿到参数后, 就能向写 App 一样来编写 Swift 代码.

参考:
Swift Package Manager使用
IOS套件管理-CocoaPods 以及 Swift package manager(SwiftPM) 兩種方式介紹

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,406评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,732评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,711评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,380评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,432评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,301评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,145评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,008评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,443评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,649评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,795评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,501评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,119评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,731评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,865评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,899评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,724评论 2 354