Swift Package Manager with a Mixed Swift and Objective-C Project (part 1/2)

Joe Susnick
3 min readOct 10, 2019

Developing with Swift Package Manager is not intuitive. Here’s what I learned over the past few weeks of working with it.

Important facts before we start:

  • A Package.swift file is basically just providing a recipe for how to build your library.
  • When you read the term “Package Manifest”, it is referring to your Package.swift file.
  • As of today 10/10/19, you cannot have mixed Swift and Objective-C files in the same package’s source code. (They may exist in the same ‘Source’ directory since you can explicitly exclude files from being compiled)
  • You should not need to change your projects directory structure to build your package. The package manifest should conform to your project, not the other way around.

Environment and Project Setup:

Setting up the Package:

You will need to add a “README.md” and a “Package.swift” file at the root of your project. Warning: The casing is important for the file name and extension.

Once you do that, close any open Xcode projects and then use Xcode to open your Package.swift file directly. This will generate a hidden directory named ‘.swiftpm’ that has a workspace for your package.

Every time you make a change to “Package.swift” it will run a command: “Resolve Swift Packages”.

The build logs will show if you have issues with the package manifest

If the packages are resolved correctly, you will see a valid target with the name of your package.

A successfully resolved package manifest gives us a valid scheme to build

Once you have this, amend your last commit. I choose to amend over adding new commits because typically a commit is to mark a point in time where things are working. What we’re doing from here on out is more of a debugging process.

Setting up the Sample Project:

Next we’ll need to create a sample project to test our package.

Just because a package builds in its own workspace does not mean it will build in the context of the project that is consuming it!!!

There are two ways to do this:

The easy way:

Open finder and drag the Package.swift file from the finder window into your project.

Alternately you can also just drag the directory that contains the Package.swift file.

The hard way:

Select: File -> Swift Packages -> Add Package Dependency

For the repository url, add an absolute file path to your project like so:

file:///Users/<you>/path-to-your-project

Note: You may need to add an initial git version tag in order for the package manager to consider your project valid.

Instead of version, select “Branch” and set it to the branch where you added the initial package commit. This may be master if you never checked out a new branch. :P

It’s doubtful that your sample project will compile. The good news is that now you have some errors you can start fixing.

Make Changes:

There are two ways to do this:

The easy way:

If you used the first technique to add a package (dragging Package.swift from finder), simply rebuild.

The hard way:

  1. Make the change in the original project (package workspace).
    Make sure your package manifest is still valid and that your schemes / targets still build.
    Add the changes in git and amend your most recent commit.
  2. Refresh the package in your sample project with:
    File -> Swift Packages -> Update to Latest Package Versions
    This will fetch any changes and update the checked-out copy of the package.

Pro-Tip: Add a keybinding to update the package. Go to File -> Preferences and select ‘Keybindings’. Search for Swift Package and update the command for “Update to Latest Package Versions” to be something convenient. I chose “⌥⇧⌘U” aka, ‘Command, Shift, Option, U’. This micro-optimization has saved me a ton of time so far.

Next Steps:

Read part 2!

Thanks for reading!

--

--