Working with Swift Packages

Xcode 11's Swift Package Manager integration is subjectively awesome. Especially for people creating and build SwiftPM packages and projects. However there are two main pain points - working with multiple packages at the same time and editing your dependencies.

Working with multiple packages

When you're building a complex app or library, the chances are you'll be working on more than one Swift package. You might have a package that contains models you share between iOS and the server and the main server project. Or you might be building a blogging engine that consists of the main engine, the repository implementations and an example application that integrates everything.

Working with individual projects can be difficult if you're developing everything together. Let's say you want to add a new API that performs a different database operation. You need to add the new route to your engine, and a new function to the Repository protocol and write the tests for that. You then need to commit, tag and release that and hope it works in the way you want with a real database. You then need to go into the repository implementation and update to the latest version. Then you must implement the new protocol requirements and commit, push and tag and release that. Finally you can go into the main application and join it all together to actually use your new route! However, more than likely, you made a mistake or didn't consider a use case that's come up. To rectify this, you have to go and do the whole dance again. What you want is to be able to work on all three codebases at once.

Editing your dependencies

If you're working on a Vapor app, you may come across a bug, or missing feature in one of the new Vapor 4 release candidates. How do you go about adding the new feature or fixing the bug if Xcode won't let you edit the code? You could fork the repository, clone and download it and work in there. But then you're left in the same situation where you're not sure if it works in the real world. Again, you want to be able to work on both codebases at once.

Swift Package Workspaces

Thankfully, Xcode already has a solution for this - the trusty workspace! In Xcode, create a new, empty workspace. Once created, find the directory for the package you want to work on and drag that directory into the project navigator in Xcode. That will create a Swift Package in Xcode and download the dependencies as normal.

However, now drag another package you're also working on, such as one of the dependencies into the project navigator. This replaces the existing project's cloned dependency with your local copy. You can now work on the packages side-by-side, commit and push when needed and generally have a better time!

Multiple Swift Packages in an Xcode Workspace

Note: there is currently an issue or feature in Xcode where it doesn't expose all the schemes for all packages you're currently working on by default. You may need to add these manually. I've raised this as FB7537293.

When you're finished, just delete the package you no longer want to work on. Xcode will detect the change and automatically switch back to the remote dependency. Make sure you select Remove Reference instead of Move to trash otherwise you'll delete your local copy of the package!