创立 Package
mkdir somePath
cd somePath
swift package init (--type library/executable/empty/system module)
其间,type 的四种类型别离对应:
- library: 库(默许)
- executable: 可执行文件
- empty: 空项目
- system module: 体系模板项目
一般情况下默许即可
创立 package 之后,还能够运用 swift package generate-xcodeproj 创立一个Xcode项目来编译和调试代码
运用 Package
在 Xcode 菜单栏中,选择 file -> add packages
能够指定 package 的版别规矩
维护 Package
版别控制
在 package 途径下,运用 git init 来创立一个库房。之后上传至远端即可
本地调试修正
对于经过 cocoapods 引进的库,如果想在本地修正该库并提交的话,需要在 PodFile 里边把途径改成本地的,然后再 pod install 一下,比较费事
可是修正 swift package 引进的库就很方便了,直接把 package 的文件目录拖到工程目录下即可。修正好提交到远端之后,右键 delete -> remove reference (move to trash 会删掉本地文件)
然后 file -> packages -> update to latest,即可更新到最新的版别
Package 之间的依靠
在每个 swift package 的目录下都有个 Package.swift 文件。内容如下:
// swift-tools-version:5.5
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "some name",
products: [
// Products define the executables and libraries a package produces, and make them visible to other packages.
.library(
name: "some name",
targets: ["some name"]),
],
dependencies: [
// Dependencies declare other packages that this package depends on.
// .package(url: /* package url */, from: "1.0.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 this package depends on.
.target(
name: "some name",
dependencies: []),
.testTarget(
name: "some name",
dependencies: ["some name"]),
]
)
其间的字段别离表示:
- name: 库/项目姓名
- products: 库/项目生成的东西,能够是 library 或者 executable. 同一个库/项目能够生成多个 library 或者 executable
- dependencies: 此库/项目所依靠的库,及依靠库的 URL 和版别等信息。如果依靠本地库的话,能够添加
.package(path:"local path") - targets: 库/项目生成的方针
相较于 cocoapods,swift package 还是愈加方便点的,而且是苹果自家的产品。可是现在许多三方库都在 cocoapods 上,swift package 的大面积遍及还需要一段时间
混编问题
target 拆分
Apple 官方文档里说:
Targets can contain Swift, Objective-C/C++, or C/C++ code, but an individual target can’t mix Swift with C-family languages. For example, a Swift package can have two targets, one that contains Objective-C, Objective-C++, and C code, and a second one that contains Swift code.
也就是说,SPM 是支撑 objc 以及 C 系代码的。可是同一个 target 里边只能有一种言语,Swift 文件不能和 objc 文件放到一个 target 里。
如果咱们想要在一个 SPM 库房里边一起放置两种言语的代码的话,就需要将库房拆分为两个 target:
let package = Package(
name: "MyModule",
platforms: [.iOS(.v11),
.macOS(.v11)],
products: [
// Products define the executables and libraries a package produces, and make them visible to other packages.
.library(
name: "MyModule",
targets: ["MyModule", "MyModule_Objc"])
],
dependencies: [
// Dependencies declare other packages that this package depends on.
// .package(url: /* package url */, from: "1.0.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 this package depends on.
.target(
name: "MyModule_Objc",
dependencies: [],
publicHeadersPath: "include",
cSettings: [.headerSearchPath(".")],
cxxSettings: [.headerSearchPath(".")]
),
.target(
name: "MyModule",
dependencies: ["MyModule_Objc"],
path: "Sources/MyModule",
swiftSettings: [.define("SPM_MODE")]
),
.testTarget(
name: "MyModuleTests",
dependencies: ["MyModule"]),
]
)
其间,库房文件结构应该为:
- MyModule
|
|-README.md
|
|-Package.swift
|
|-Sources
|
|-MyModule
| |
| |- MyPackage.swift
|
|-MyModule_Objc
|
|-Include
| |
| |- MyObjCClass.h
|
|- MyObjCClass.m
Sources 文件夹拆分为两个子文件夹,别离是两个 target 的途径。Swift target 依靠 objc 的 target, objc 的 target 能够设置揭露 header 的途径。
这样,objc 以及 C/C++ 这些 C 系的文件都放在 MyModule_Objc 文件夹下,Swift 文件放到 MyModule 文件夹下,就能够在同一个 SPM 库房下完成混编了。
引证以及和 cocoapods 的兼容问题
在上面的 package 设置里边能够看到一行预处理宏的界说:
swiftSettings: [.define("SPM_MODE")]
这个设置是用来标识当时库是经过 SPM 方式引进的。根据上文,SPM 形式下,当时库的 Swift 和 objc 是两个 target。因而,同一个库的 Swift 文件想要调用 objc 文件的话,有必要引进 objc 的 target:
import MyModule_Objc
// your code...
可是,咱们的库一般情况下还是要支撑 cocoapods 的。在 cocoapods 形式下,同一个库房的 Swift 和 objc 文件是不需要拆分为两个 target 的,pod 是经过桥接文件等来完成两者之间相互调用的。
那么问题就来了,当运用 cocoapods 引进当时库时,import MyModule_Objc 是肯定会报错的,因为 pod 并不会生成 MyModule_Objc。
这时候,咱们在 package 文件里预先界说的宏就派上用场了:
#if SPM_MODE
import FoundationX_Objc
#endif
只有在 SPM 形式下,才会 import MyModule_Objc,这样就解决了与 cocoapods 的兼容问题。

