Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?

Using Swift Package Manager with iOS

Step 1:

File > New > Project...

Step 2:

Create a Package.swift file in your root project directory, add dependencies, then run swift package fetch on the command line in the same directory. We’re not going to run swift build because it will just complain.

Step 3:

Open the Xcode project and make sure it builds. Now we need to create a new Target for each dependency. Go to File > New > Target… and create a new “Cocoa Touch Framework” target for each dependency. Once your finished you should notice a bunch of new groups in your Project Navigator representing the new targets, I recommend placing these in a Dependencies group. You can also eliminate the ‘<target_name>.h’ files if you don’t need Obj-C support.

Step 4:

This step is a little tricky so read closely. We need to add all the files located in the dependency’s Packages/DependencyName/Sources folder into our project. Select the dependency’s group in the Project Navigator and hold down ⌘ + ⌥ + A to add files, highlight all the files in the dependency’s Sources folder, click the options button in the bottom left to reveal the list of targets and be sure to add the files to the correct target before clicking Add. Also be sure to uncheck your project’s target so you don’t add them to both the dependency and your project, this is unnecessary.

Now we need to configure “Linked Frameworks and Libraries” for each dependency target. This requires knowing what dependencies depend on each other—the best way to understand this is to open up each dependency’s Package.swift file. Click through each Target in your project and go to General > Linked Frameworks and Libraries to click the + button. For your project target you will need to add all dependencies.

(Note: Dependencies are addative, meaning if Dep A requires Dep B and Deb B requires Deb C & D, you'll need to be sure Dep A has Deps B C & D in its Linked Frameworks and Libraries)

Everything should build at this point. If not then double check Linked Frameworks to ensure they are correctly added.

Cleanup:

By creating all these new targets you’ve also added a bunch of folders to your project directory. Each one has a single Info.plist file in them and I like to stuff these inside my project's .xcodeproj file. Right click on the project file and choose Show Package Contents, then rename each Info.plist to DependencyName_Info.plist and move them inside the project file. Then open project.pbxproj in a text editor (not Xcode) and search for INFOPLIST_FILE references. Replace: INFOPLIST_FILE = DependencyName/Info.plist; with ProjectName.xcodeproj/DependencyName_Info.plist;. The next time you open your Xcode project you will see red Info.plist files in your dependency folders, you can delete those.

Problems with approach:

  • This is a manual process prone to error—someone could probably write a script 🤔. Hopefully Apple will add iOS support to the swift package generate-xcodeproj command-line utility.
  • When you run swift package update you’ll need to then manually examine all your dependency targets. If a file just changed it's fine, changes get picked up automatically but if new files were added or removed you'll need to account for those.
  • This may not work as well for more complicated dependencies, I've only used it with very basic stuff.

TofPlay commented Feb 23, 2017

Hopefully Apple will add iOS support to the swift package generate-xcodeproj command-line utility

Do you have the date when it will be available? With Swift 3.1?

What is ⌘ + ⌥ + A? This is doing nothing for me

eonist commented Jul 12, 2017

Does this work? Any word on official SPM support for iOS soon? I really love SPM for macOS

There is a better way with Swift v4 which doesn't require you to manually copy dependency files.

https://github.com/j-channings/swift-package-manager-ios

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment