We’ve come a long way! We learned a lot about Swift Concurrency, from using async/await to writing custom actors. You may feel more comfortable using concurrency in your projects, but the most significant step is yet to be taken: migrating existing code to Swift Concurrency.

I’ve been working 7,5 years at WeTransfer, migrating two large projects from Swift 3 all the way to Swift 5.8 eventually. That means I’ve only scratched the surface regarding Swift Concurrency, but I did experience some impactful changes. March 2024, I went full-time indie to work on this course, as well as on RocketSim. The latter is a large personal project with several packages that I’ve slowly been migrating to Swift 6. The learnings from both are what allowed me to create this course.

In the next modules, we will dive deeper into migration strategies. Migrating will be challenging, and it will likely be even harder for projects that are older. It’s a case-by-case scenario, and one might find migrating easier than another. Yet, there are a few common challenges.

The Swift Concurrency Rabbit Hole

The first thing I want to mention is what I like to call “The Swift Concurrency Rabbit Hole”. You build your project with strict concurrency enabled (more on this later) and you encounter 50+ errors and warnings. You fix a bunch, build your project again, and voila: 80+ errors appear.

In other words, fixing something here introduces a problem elsewhere. It can be demotivating and challenging to stay positive. Yet, with the right mindset and strategy, this is all manageable.

Why the right strategy matters

It’s essential to realize that migration becomes easier when you take the right steps. Incrementally and focused, without too much pressure. Prepare yourself to take two steps back before you can take five steps forward.

I’ll be sharing what I believe is the best approach for existing projects and packages, old or new, small or large. My goal is to provide you with an overview of approaches and tools to work through challenging code changes along the way.

A migration full of temptations

If you’re sensitive to refactoring old code, you should prepare yourself with a different mindset. If there’s one challenge during migration, it’s ignoring the temptation to refactor more than necessary. More minor changes, focused solely on concurrency, will bring you to your final step more quickly. I’ll provide more details on this later.

Letting go of the traditional threading mindset

We’ve briefly discussed this in the first module of this course: letting the traditional threading mindset go. We should trust Swift Concurrency and the compiler to handle threading well and focus on providing instructions. By setting priorities and isolation domains correctly, Swift Concurrency can optimize running tasks in the most optimal manner. That means we no longer think about running something on a background thread, but instead thinking of which isolation domain: nonisolated, @MainActor isolated, or any global actor isolation.

Summary

This is just a brief introduction into migrating to Swift Concurrency and the challenges it might bring. The next lessons will go deeper into challenges and will provide you migration habits and techniques for a successful migration.