Swift Package Manager使用总结

1、简介

Swift Package Manager(如下简称SPM)是苹果在swift3.0中加入的一个包管理工具,用于处理模块代码的下载、编译和依赖关系等。跟CocoaPods和Carthage功能相似,不过比这两个更简洁,代码的侵入性更小,也不须要额外安装工具。git

须要注意的是,SPM在swift4.0中从新设计了API,因此你须要肯定你当前使用的swift版本,不然极可能会出现build失败的状况,如下代码都是基于swift4.0版本。github

2、使用教程

既然是包管理,因此咱们的操做都是以包的形式,依赖的第三方库都会当成一个个单独的包来处理,依赖包能够嵌套。macos

SPM包含两种包:可执行的二进制包(executable)和静态库包(Library),二者惟一的区别就是前者会生成二进制可执行文件,能够直接用命令行执行。若是建立的是Library,用命令行执行会提示没有可执行文件,这个时候只须要在Sources/目录下建立一个main.swift文件就能够执行了。json

一、经过命令建立包:swift

$ mkdir SPMDemo    
$ cd SPMDemo         
$ swift package init --type executable(or library)  //初始化包,不带参数的话默认是Library
Creating executable package: SPMDemo
Creating Package.swift
Creating .gitignore
Creating Sources/
Creating Sources/main.swift
Creating Tests/
$ swift build    //编译并生成可执行的二进制文件
Compile Swift Module 'SPMDemo' (1 sources)
Linking ./.build/debug/SPMDemo
$ swift run 	//执行生成的文件
Hello, world!   //执行效果
复制代码

二、加入依赖包xcode

咱们须要在前面建立的包中使用第三方库(这里以SwiftyJSON为例),编辑Package.swift文件:bash

// swift-tools-version:4.0
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
    name: "SPMDemo",
    dependencies: [
        // Dependencies declare other packages that this package depends on.
        .package(url: "https://github.com/SwiftyJSON/SwiftyJSON.git", from: "4.0.0"),	//第三方库url和版本号
    ],
    targets: [
        // Targets are the basic building blocks of a package. A target can define a module or a test suite.
        // Targets can depend on other targets in this package, and on products in packages which this package depends on.
        .target(
            name: "SPMDemo",
            dependencies: ["SwiftyJSON"]),	//依赖的包名称
    ]
)
复制代码

注:关于dependencies的格式定义能够看这里有详细说明文档,能够指定分支、具体的commit编号、版本范围等等。app

而后咱们检验一下引入的依赖包是否可用,编辑Sources目录下的main.swift文件:工具

import SwiftyJSON	//引入模块

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

print("Hello, world!")
复制代码

保存以后咱们再run一下:ui

$ swift run
Fetching https://github.com/SwiftyJSON/SwiftyJSON.git
Cloning https://github.com/SwiftyJSON/SwiftyJSON.git
Resolving https://github.com/SwiftyJSON/SwiftyJSON.git at 4.0.0
Compile Swift Module 'SwiftyJSON' (1 sources)
Compile Swift Module 'SPMDemo' (1 sources)
Linking ./.build/x86_64-apple-macosx10.10/debug/SPMDemo
{
  "name" : "Jack",
  "age" : 25
}
Hello, world!
复制代码

能够看到输出了咱们的json结构体,说明引入依赖包成功了!

注:第一次run的时候SPM会先将依赖的库克隆下来并编译好放在.build隐藏文件夹中,若是把这个文件夹删除从新run,会从新下载。

三、如今咱们来试试本身定义一个库做为其余项目的依赖包

$ mkdir MyLib    
$ cd MyLib         
$ swift package init	//初始化包,不带参数的话默认是Library
Creating library package: MyLib
Creating Package.swift
Creating README.md
Creating .gitignore
Creating Sources/
Creating Sources/MyLib/MyLib.swift
Creating Tests/
Creating Tests/LinuxMain.swift
Creating Tests/MyLibTests/
Creating Tests/MyLibTests/MyLibTests.swift
复制代码

建立Library的话默认是没有main.swift文件的,Sources目录下只有一个MyLib.swift文件,它给咱们定义了一个结构体,但并非public的,咱们知道swift中只有被public和open修饰才能被其余模块访问,因此咱们把它改为public:

public struct MyLib {
    var text = "Hello, MyLib!"
    public var num:Int
    public init() {
        num = 2
    }
}
复制代码

而后咱们build一下,确保咱们的Library能顺利编译经过。

由于SPM依赖包必须使用git url和版本号,因此咱们须要为咱们的库建立一个git仓库并提交代码和打tag:

$ git init
$ git add .
$ git commit -m "Initial Commit"
$ git tag 1.0.0
复制代码

接下来修改前面的Package.swift文件,加入咱们的Library:

dependencies: [
        // Dependencies declare other packages that this package depends on.
        .package(url: "https://github.com/SwiftyJSON/SwiftyJSON.git", from: "4.0.0"),
        .package(url: "./MyLib", from: "1.0.0")    //由于没有推送到远程仓库,因此这里用相对路径,from就是咱们刚才打的tag
    ],
    targets: [
        // Targets are the basic building blocks of a package. A target can define a module or a test suite.
        // Targets can depend on other targets in this package, and on products in packages which this package depends on.
        .target(
            name: "SPMDemo",
            dependencies: ["SwiftyJSON","MyLib"]),      //添加依赖包名
    ]

复制代码

而后咱们再检验一下依赖包是否可用,编辑main.swift文件:

import SwiftyJSON
import MyLib

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

//自定义库
let lib = MyLib()
print(lib)
复制代码

而后咱们再run一次看看:

{
  "name" : "Jack",
  "age" : 25
}
MyLib(text: "Hello, MyLib!”, num: 2) 复制代码

结果输出了咱们自定义的库中结构体的内容,说明咱们引入自定义依赖包成功了!

3、如何在iOS工程中使用SPM

除了macOS之外,目前SPM不支持苹果其余平台,因此若是想替换Pods或者Carthage仍是谨慎一点,等苹果彻底支持iOS之后再切换过来吧。不过咱们能够以引入子工程的方式在iOS项目中使用SPM,具体步骤以下:

一、建立新的iOS项目或者使用已存在的项目

二、将该工程初始化为SPM(swift package init)

三、建立一个空的依赖源文件和路径,由于建立xcodeproj文件的时候须要至少一个源文件,这里我在dep-sources路径下建立一个Dependencies.swift文件:

$ mkdir dep-sources
$ cd dep-sources/
$ touch Dependencies.swift

复制代码

四、修改Package.swift文件,加入依赖库并设置target为新的名字,不然会跟iOS工程的target重名,这里我改成Dependencies,而后在target中设置第3步的路径

// swift-tools-version:4.0
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
    name: "Dependencies",
    products: [
        // Products define the executables and libraries produced by a package, and make them visible to other packages.
        .library(
            name: "Dependencies",
            type: .static,
            targets: ["Dependencies"]),
    ],
    dependencies: [
        // Dependencies declare other packages that this package depends on.
        // .package(url: /* package url */, from: "1.0.0"),
        .package(url: "https://github.com/SwiftyJSON/SwiftyJSON.git", from: "4.0.0"),
        .package(url: "https://github.com/Alamofire/Alamofire.git", from: "4.6.0")
    ],
    targets: [
        // Targets are the basic building blocks of a package. A target can define a module or a test suite.
        // Targets can depend on other targets in this package, and on products in packages which this package depends on.
        .target(
            name: "Dependencies",
            dependencies: ["SwiftyJSON","Alamofire"],
            path: "dep-sources" //源文件路径
        )
    ]
)

复制代码

五、执行swift package generate-xcodeproj命令,这里会生成Dependencies.xcodeproj

$ swift package generate-xcodeproj
Fetching https://github.com/SwiftyJSON/SwiftyJSON.git
Fetching https://github.com/Alamofire/Alamofire.git
Cloning https://github.com/SwiftyJSON/SwiftyJSON.git
Resolving https://github.com/SwiftyJSON/SwiftyJSON.git at 4.0.0
Cloning https://github.com/Alamofire/Alamofire.git
Resolving https://github.com/Alamofire/Alamofire.git at 4.6.0
generated: ./Dependencies.xcodeproj
复制代码

六、打开iOS工程,将第5步生成的project拖入工程做为sub-project,而后添加依赖的framework就能够了(xcode9常常莫名其妙抽风,建议作完后关闭从新打开工程)

七、验证引入包是否成功

4、可能碰到的问题

一、no such module

$ swift build
Compile Swift Module 'SPMDemo' (1 sources)
/SPMDemo/Sources/SPMDemo/main.swift:2:8: error: no such module 'MyLib'
import MyLib

复制代码

这有多是你只加入了依赖包的路径而没有在target中加入模块名称

targets: [
        // Targets are the basic building blocks of a package. A target can define a module or a test suite.
        // Targets can depend on other targets in this package, and on products in packages which this package depends on.
        .target(
            name: "SPMDemo",
            dependencies: ["SwiftyJSON"]),      //缺乏“MyLib”
    ]
复制代码

还有一种状况是更新了依赖包,可是没有构建到.build目录下,这个时候只要把.build文件删除,从新构建一次就能够了。有什么问题欢迎留言讨论!

相关文章
相关标签/搜索