Swift Package Manager Guide – the time to shine is now! (1/2)

5 min

read

The Swift Package Manager has been around for some time, but it is with the release of Xcode 11 that it finally gets its true chance to shine. Now you can use it across the entire Apple ecosystem. Which makes for a great opportunity to delve a bit deeper into the subject. Learn more about SPM and its new features from our 2-part guide.

Regardless of whether you use 3rd party dependencies, develop your own internal frameworks, or just want to extract part of your app’s code to make it more modular and orderly (or everything at once), Swift Package Manager can be very helpful. With the release of Xcode 11, it’s going to become a very important part of Apple’s IDE. Now, SPM packages work with all Apple platforms, including the iOS system (so far, it supported command line tools and server-side Swift apps only). If you haven’t used SPM yet, now is the best time to give it a try!

Swift Package Manager for iOS and more

What exactly can Swift Package Manager do for you?

  • It automatically adds dependencies to Frameworks, Libraries and Embedded Content in a target (unlike Carthage).
  • It automatically adds embedded dependencies (packages used by libraries you added) to your project (another missing feature in Carthage).
  • It allows you to delete unneeded libraries at a click of a button (missing in CocoaPods).
  • It makes it easy to edit packages by overwriting references to dependencies with a local version.

In my 2-part Swift Package Manager guide, I’ll show you how to take advantage of SPM’s potential. Today, I’ll focus on using SPM to consume both private and public libraries. The soon-to-be published 2nd part will tackle the issue of using SPM to help create your own modules and edit the source code of your dependencies. I hope that by the end of the guide, you’ll love the idea of working with SPM as much as I do!

Xcode -> File -> New 😍

Let’s say you’re working on a project of an iOS app for a client from the insurance industry. A desktop app for agents already exists. Now, the task is to create a simplified version for potential clients. Its main purposes include gathering data (basic personal data, risk factors and declarations) and calculating premiums.

Create a new Workspace (File -> New… -> Workspace) and a new app project (File -> New… -> Project). Also, make sure:

  • to add the project to the Workspace and to its group.
  • not to tick the ‘Create Git repository on my Mac‘ box. We will later create a high-level repository that will include the whole Workspace.

Now, create a repository at the same level as the catalog that contains the *.workspace file and the project directory. I wasn’t able to force Xcode’s version control (In the Source control menu) to let me create a repository where I wanted to, so I did it via the terminal (see the screen below). I also added a .gitignore file.

📦 Internally developed library

Let’s assume that the team responsible for the macOS app created a library called InsuranceCulculator, which includes all the logic that calculates premiums. Using the same library across both apps will not only speed things up, but also ensure that agents and clients will see the same results.

* By the way, if you are wondering how to share your code to your internal team or even the entire public, so that it can be added with Swift Package Manager, make sure to read the upcoming second part of the guide. In doing so, our SPM story will come a full circle. ♾️⚠️

In order to access packages in your company’s repository, make sure to properly configure your Github/Bitbucket/GitLab account in Xcode (Xcode -> Preferences -> Accounts).

Now, that we took care of all that, we can add our first Swift package! 🎉

Adding dependencies to a project

Go to File -> Swift Packages -> Add Package Dependency – a new window will open. By default, it shows all of the repositories you own. A search can be used to find a specific repository out of those you have access to. Choose insurancecalculator and click Next. Now, choose which version you want to use (more about available options in a moment) and specify a target for this new dependency. It’s done!

Swift Package Manager can now download a repository that contains the library, checkout the proper version, add the library to Frameworks, Libraries, and Embedded Content in the specified target and add a reference to the dependency in the project. All of that happens automatically (or magically, if you’d rather 🔮).

🥳 Voilà! Now you can import InsuranceCalculator to the InsuranceApp and get to calculating those premiums!

import UIKit
import InsuranceCalculator

class ViewController: UIViewController {

override func viewDidLoad() {
super.viewDidLoad()

let customer = Person(age: 33)
let interval = DateInterval(start: Date(), duration: 60*60*24*365)
let premiums = InsuranceCalculator.calculatePremiums(for: [.car, .flat], insuredBy: customer, in: interval)
print("calculated premiums: \(premiums)")
}
}

The console now shows the value of calculated premiums to be 20813760.0

Versions, versions, versions…

Now is a good moment to learn how you can specify the version of a dependency you add to a project.

The version management process is quite similar to what you might know from Carthage or Cocoapods. There are three groups of rules at our disposal:

  • version-based: prioritizes the version of a given library (according to the Semantic Versioning 2.0.0 standard),
  • branch-based: references a branch in the package’s repository,
  • Commit-based: references a specific commit (using its SHA-1 hash).

The version-based strategy is the most popular one and is usually recommended. It allows you to easily specify how important updates (referred to in this context as significant changes) should be accepted. The choices include:

.upToNextMinor(from: "5.0.1")

.upToNextMajor(from: "5.0.1")

A more restrictive approach which specifies a range (e.g. 3.1.0” … “3.1.2”) can also be used. Another, most restrictive option is to simply specify a single compatible version (.exact (“5.0.1”)). This approach is usually not recommended, since it can cause conflicts in the dependency graph if more libraries use the same dependencies in different versions. You will also lose access to bug fixes.

You also should keep in mind that before you publish your package’s version, you are required to remove all dependencies based on branches and commits.

It works for me…

Let’s say that your friend is cloning the repository and for some reason can’t build the project. If you come across such problems, check if your friend properly connected their account to the company repository in Xcode. You should also check if they use SSH.

📦 3rd party library

So far so good! Still, I doubt you have missed this awful line 😉

let interval = DateInterval(start: Date(), duration: 60*60*24*365)

We can definitely do better. Start by adding the SwiftDate library. It will help us to express the duration time in a more concise manner.

Use the File -> Swift Packages -> Add Package Dependency… menu to add a link to the SwiftDate GitHub repository. The remaining steps are the same as before.

🥳 Voilà! SwiftDate is ready to be imported and used! 🎉

import UIKit
import InsuranceCalculator
import SwiftDate

class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()

let customer = Person(age: 33)
let interval = DateInterval(start: Date(), duration: 365.days.timeInterval)
let premiums = InsuranceCalculator.calculatePremiums(for: [.car, .flat], insuredBy: customer, in: interval)
print("calculated premiums: \(premiums)")
}
}

The value of calculated premiums remains the same: 20813760

It was easy, wasn’t it? Thank you, Swift Package Manager!

Removing dependencies

Want to remove some dependencies? It only takes a moment! Select a project in the Projects and targets list in Xcode, go to the Swift Packages tab (next to Info and Build settings), mark packages to be removed and click the “-” sign. Done.

Summary

In the first part of my Swift Package Manager guide, I focused on working with existing public and private packages. Package management with SPM is really fun. It only takes a couple clicks to add a new library in a specific version. All packages are updated according to the rules you choose. In addition to that, a new Project Navigator section Swift Package Dependencies makes it easy to view all the dependencies we have added to a project. With that, finding unneeded dependencies and keeping things clean is a walk in the park.

Do you now feel like trying and using Swift Package Manager in your everyday work? You don’t necessarily need a new project to do that. There are plenty of articles available online that will guide you through the process of migrating from CocoaPods or Carthage to SPM. It will also serve as a great opportunity to review the libraries in your projects and check if there is something that should be removed. Also, if you want even more Swift-related content, check out my introduction to protocol-oriented programming with Swift.

Estimate your project





or contact us directly at [email protected]

Thanks

Thank you!

Your message has been sent. We’ll get back to you in 24 hours.

Back to page
24h

We’ll get back to you in 24 hours

to address your needs as quick as possible.

Estimation

We’ll prepare an estimation of the project

describing the team compostition, timeline and costs.

Code review

We’ll perform a free code review

if you already have an existing system or a part of it.

Our work was featured in:

Tech Crunch
Forbes
Business Insider

Aplikujesz do

The Software House

Aplikuj teraz

wyślij CV na adres: [email protected]

CopiedTekst skopiowany!

Nie zapomnij dodać klauzuli:

Kopiuj do schowka Copy

Jakie będą kolejne kroki?

Phone

Rozmowa telefoniczna

Krótka rozmowa o twoim doświadczeniu,
umiejętnościach i oczekiwaniach.

Test task

Zadanie testowe

Praktyczne zadanie sprawdzające dokładnie
poziom twoich umiejętności.

Meeting

Spotkanie w biurze

Rozmowa w biurze The Software House,
pozwalająca nam się lepiej poznać.

Response 200

Response 200

Ostateczna odpowiedź i propozycja
finansowa (w ciągu kilku dni od spotkania).

spinner