13. July 2019

Dependency Management for iOS projects with the Swift Package Manager

With Xcode 11, the Swift Package Manager has been extended for use in iOS projects. It can now be used to create iOS frameworks / modules and integrate them into Xcode projects. This makes the tool an alternative to Cocoapods and Carthage for managing the dependencies of an iOS project.

The following tutorial shows the steps for integrating the 3rd party library Kingfisher for asynchronous loading of images - this library already provides the metadata required for the Swift Package Manager in a separate branch.

  1. Download the example project ImageDownload. This contains the basic structure for an app that displays images in a TableViewController:

    Simulator ImageDownload Example

  2. Select File » Swift Packages » Add Package Dependency ... to add a new dependency and specify the Clone URL of the Kingfisher library: https://github.com/onevcat/Kingfisher.git:

    File » Swift Packages » Add Package Dependency…

  3. Specify xcode11 as branch:

    Branch angeben

  4. The library is now set up in the project and displayed in the Project Navigator:

    Xcode Swift Package Dependencies
  5. In the project under Swift Packages the version information can be changed, e.g. to upgrade to a new version:

    Swift Package Version

  6. Use the library in FruitsTableViewController: Import the Kingfisher module there and use the kf extension to start a picture download asynchronously in the background:

    import UIKit
    import Kingfisher
    
    class FruitsTableViewController: UITableViewController {
    
        // ...
        
        override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            // ...
            let placeholder = UIImage(named: "placeholder")
    cell.fruitImage.kf.indicatorType = .activity
    cell.fruitImage.kf.setImage(with: fruit.image, placeholder: placeholder)
            // ...
        }
        
    }

Q&A

Where is the checked-out module stored?

In the Derived Data folder of Xcode:

Xcode Derived Data

What happens if the project is opened without the library already downloaded?

The library is automatically downloaded by Xcode:

Dependency Fetching

What happens when a new version of the library is released?

The dependency can be updated with File » Swift Packages » Update to Latest Package Versions.

When Xcode fetches the dependency it always loads the latest version that meets the projects version rules.

Unfortunately, currently Xcode does not support version pinning. This helpful feature of f.e. CocoaPods, which locks down the versions in a file Podfile.lock and guarantees that all developers use the identical version, is still missing in Xcode.

Therefore, it’s a good idea to specify an exact version number as the Version Rule, or even specify the commit ID, because that also guarantees that the library sources cannot change without being noticed.