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文件刪除,從新構建一次就能夠了。有什麼問題歡迎留言討論!

相關文章
相關標籤/搜索