Swift Package Manager is a powerful solution for managing dependencies and creating modular apps. Over the years, Xcode support for SwiftPM has gradually improved, streamlining the development workflow. In Xcode 13, discovering and managing third-party Swift packages became a little easier with the introduction of Swift Package Collections.
A Package Collection is a JSON file that describes a curated list of packages that can be shared directly or online. It can also be signed to prevent tampering. Collections can be a great way to share dependencies across an organization or make frequently used packages more accessible.
Xcode is pre-configured with a single Package Collection published by Apple. Adding an import statement to a file for one of the packages in this collection results in a fix-it prompt to add the dependency to the project. Adding new collections can enable this same fix-it for other Swift Packages. The Swift Package Index maintained by Dave Verwer and Sven A. Schmidt makes it easy to find Swift Packages as well as Package Collections.
Add a Package Collection in Xcode
Adding a collection, like the Pointfree open-source packages, to Xcode is straightforward.
Steps to add a collection:
- Within Xcode, click File > Add Packages…
- Under Package Dependencies, click the +
- In the bottom left corner of the package browser, click the +_ and select Add Package Collection…
- Paste the URL to the Package Collection
- Confirm by clicking Add Collection⠀
Once added, it is easy for Xcode to find and import your favorite packages. Try importing a module that isn’t already a project dependency, and Xcode will warn you. But if the package is part of a package collection registered with Xcode, then Xcode will provide a fix-it that will automatically add the dependency to the project.
Add a Package Collection from the Command Line
Using the Pointfree open-source collection of Swift packages as an example, the following command will add the collection to SwiftPM and make it available in Xcode.
1$ swift package-collection add https://swiftpackageindex.com/pointfreeco/collection.json
Creating Your Own Swift Package Collections
Creating new collections can be a convenient way to share common packages used internally within an organization or to group related packages of an open-source project, like Vapor.
Step 1: Define the input of the package collection in a JSON file
To get started, create a JSON file describing the metadata for the collection and the packages to include. At a minimum, the packages should contain a Github URL, but you can also specify additional information to provide additional context. Check out the README to learn more about the options.
1{
2 "name": "Collection Example",
3 "overview": "This is a sample package collection.",
4 "keywords": [
5 "SwiftUI Navigation",
6 "Composable Architecture"
7 ],
8 "packages": [
9 {
10 "url": "https://github.com/pointfreeco/swift-composable-architecture"
11 },
12 {
13 "url": "https://github.com/pointfreeco/swiftui-navigation"
14 }
15 ],
16 "author": {
17 "name": "Jane Doe"
18 }
19}
Step 2: Generate the output file with the package-collection-generate command
Apple provides the package collection generator to simplify generating the collection by filling in the detailed metadata from the repositories, including a complete list of the available versions.
The package collection generator does not currently ship with the Swift toolchain, so it needs to be built from the source.
Clone the git repository.
1$ git clone https://github.com/apple/swift-package-collection-generator.git
Build the generator from the source.
1$ swift build --configuration release
Install the commands on your system path.
1install .build/release/package-collection-generate /usr/local/bin/package-collection-generate
2
3install .build/release/package-collection-diff /usr/local/bin/package-collection-diff
4
5install .build/release/package-collection-sign /usr/local/bin/package-collection-sign
6
7install .build/release/package-collection-validate /usr/local/bin/package-collection-validate
Now, with our input.json, the generator can fill in additional metadata for each package from GitHub.
$ package-collection-generate input.json generated-output.json
The generated-output.json is now a complete description of our package collection.
Step 3: Sign Collection (Optional)
To prevent tampering with the collection, you can sign it using the package-collection-sign command. This command takes the generated JSON file as an input and generates a signed collection file. This step requires generating a signing certificate on the Apple developer portal. Check out the SwiftPM documentation for more details on the signing requirements.
1$ package-collection-sign
2generated-output.json
3
4 signed-output.json
5
6 priivate-key.pem
7
8 certificate.cer
Step 4: Distribute the collection on GitHub or the Swift Package Index
Once you have generated the package collection file, you can publish it. The file can be published to GitHub or the Swift Package Index for public collections. The collection can also be shared directly with team members for internal collections.
These steps might seem like a lot of up-front work to create a Package Collection. Fortunately, collections don’t need to be created frequently.
Conclusion
Package Collections aren’t going to save hours of development time, but they will make commonly used packages more accessible while staying in the editor flow.