
This video is only available to subscribers. Start a subscription today to get access to this and 470 other videos.
Swift Package Manager
Episode Links
Creating our Own Packages
Let's assume we want to make a dice rolling library for others to use.
We're going to make a folder to put our library in called DiceKit
:
$ mkdir DiceKit
$ cd DiceKit
Then we can create our project:
$ swift package init
This will use the name of our folder as the name of the package. If you want to change this, you can add the --name
flag and specify something else.
Note that in this folder there is no xcodeproj. This is because Swift packages leverage settings from Package.swift
as well as files on the filesystem to determine what the package contains.
Building Packages
Since there is no Xcode project, you use the command line to build packages:
$ swift build
If you inspect the file system now there's a hidden/ignored folder called .build
which contains all the built artifacts.
Let's create a simple type we can expose in this library. Create a file in Sources/DiceKit
called Die.swift
.
public struct Die {
public let numberOfSides: Int
public init(numberOfSides: Int) {
self.numberOfSides = numberOfSides
}
public func roll() -> Int {
return Int.random(in: 1...numberOfSides)
}
}
Note that this file is already part of the target because we added it to the Sources/DiceKit
folder.
There's no way for us to run this code yet because we just created a library. Let's create a command line executable that uses this library.
Creating a Command Line Swift Executable
Change to the parent directory and create a new one to contain our command-line application:
cd ..
mkdir DiceRoller
cd DiceRoller
Then we can initialize a new executable package:
$ swift init --type executable
Note that this creates a main.swift
for us, and this is the entry point where our code starts to run when the app is executed.
Next let's add a dependency for the DiceKit
library. We'll use a local path to refer to the package rather than a published version. In Package.swift
:
import PackageDescription
let package = Package(
name: "DiceRoller",
dependencies: [
.package(path: "../DiceKit")
],
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: "DiceRoller",
dependencies: ["DiceKit"]),
.testTarget(
name: "DiceRollerTests",
dependencies: ["DiceRoller"]),
]
)
Now when we build it, it will pull in dependencies and build those too:
$ swift build
Completed resolution in 0.56s
[6/6] Linking DiceRoller
If we run the app we can see that it works:
$ .build/debug/DiceRoller
Hello, World!
Let's jump back over to main.swift
and use our library:
import DiceKit
let die = Die(numberOfSides: 6)
let roll = die.roll()
print("🎲> You rolled a \(roll)")
Running swift build again, we can see that it works.
$ swift build
$ .build/debug/DiceRoller
🎲> You rolled a 4
Working in Xcode Projects
If we want to build & debug within Xcode we can, but we need to generate an Xcode project.
$ swift package generate-xcodeproj
Then if we open it we can run it, set breakpoints, etc.
Adding Packages from Xcode
If you already have an Xcode project and integrate some Swift packages you can do this from the File -> Swift Packages menu and enter in a URL to a library.
The best way that I've found to search for these packages is with SwiftPM.co.