Franz Busch
Sixt Tech
Published in
7 min readJul 3, 2019

--

Apple had all the right to say “Your minds will be blown 🤯” before this year’s WWDC. After coming back from my post WWDC vacation where I had time to think about all the fantastic things that were announced and read through many follow-up articles, I am still incredibly overwhelmed and massively impressed about what Apple revealed this year. Last year, I already had the chance to attend the conference with Sixt, and it was a very cool experience. However, this year, was on a totally different level. A colleague at Sixt and I were attending the conference and we were both completely blown away. The introduction of Combine, SwiftUI, and packages in Xcode, all display years of hard work and effort from so many people at Apple and the open source community to show what incredible potential Swift has. In this post, I want to focus on these three new features. Moreover, we want to explore a bit what this could mean for your applications and also mention a few of their current shortcomings.

Combine

First, let’s start with something that wasn’t even mentioned during the keynote, even though it is one of the biggest and most surprising revelations from this year — The Combine framework. Combine is a new framework that introduces reactive programming to Apple platforms. Most of the framework is built around two protocols. The Publisher, which delivers values to one or more Subscriber. Furthermore, it provides many operators to transform your publishers, which allows you to build complex data flows that look concise. Additionally, Combine has built-in back-pressure support which means a Subscriber can control how many values he can receive to avoid becoming flooded. One of the most important parts is that it is heavily designed for performance; therefore, not relying on Foundation and actually being lower level than it. Combine can already be seen in action in the new SwiftUI and RealityKit frameworks.

What does this mean for your apps?

If you are currently using frameworks, such as RxSwift or ReactiveSwift, in your applications, then you are already in a fantastic place. You can write small wrappers which conform your types to the Combine protocols, and the inter-op should be set up. Of course, there are some differences between Combine and the current open source frameworks but getting a handle on how Combine works, when you are already familiar with reactive programming, should not be too difficult. A good summary of the differences can be seen in this and this post.

On the other hand, if you are currently not using any reactive programming concepts in your application, it would be useful to adopt more of them over the next year so that the inevitable switch to Combine is easier. Apple already added new methods and types to current frameworks, like Foundation, which enable Combine inter-op. For your application data-flow, a good way to start is by using a lightweight Observable type to pass your data and state around the application. This way you should be able to integrate with SwiftUI and once you switch to Combine you can easily migrate the custom type to a Publisher, and you should be good to go. Lastly, Combine also provides Future and Promise types; however, the documentation and how exactly they work is not really clear. Hopefully, Combine also brings an end to the discussion on how to handle asynchronous callbacks and fills the gap until async/await is implemented in the language.

SwiftUI

How do you even start with this one? SwiftUI is Apple’s new declarative UI framework which works on iOS, iPadOS, MacOS, WatchOS, and tvOS at the same time. It is probably the biggest game-changer that Apple has announced since the initial Swift announcement, and it will have a similarly huge impact on the community. After watching all the sessions, speaking with the engineers in the WWDC labs and playing around with it, I have to say it is incredible what powerful frameworks can be created when leveraging the full potential of Swift and its type system.

Under the hood SwiftUI is powered by three new Swift language features:

  1. PropertyWrappers: Allows changing the underlying storage mechanism of properties and enables complex APIs.
  2. Return statement elision: The return keyword can now be elided for single line functions or computed properties.
  3. Function builders: Provides the capability to develop domain-specific languages in Swift.

Incremental adoption is key

Since SwiftUI is still quite new and lacks a couple of features to cover all the functionality that UIKit and AppKit offer, it is important to start by incrementally adopting it instead of completely rewriting your application with it. Gladly, Apple offered interoperability in both directions. To show a SwiftUI View in AppKit or UIKit use a UIHostingViewController/NSHostingViewController and to present a UIView/NSView in SwiftUI make it conform to ViewRepresentable. When adopting these two binding mechanisms, it should be easy enough for your app to migrate towards SwiftUI over time. Furthermore, if you start to use reactive programming patterns in your application, the interaction with SwiftUI will become a lot easier since it is based on reactive principles.

Navigation/Routing

Additionally, I want to point out one feature from SwiftUI that in my opinion is still lacking a few things. Currently, the navigation functionality inside the framework is working with NavigationButtons and NavigationLinks. While navigating through a user interaction is quite easy, doing the same through code is tricky. At WWDC we talked to some Apple engineers, and they said that they are not happy how navigation currently works and they want to provide a better API that handles common cases, such as in-app routing for deep links or push-notifications. Hopefully, they can ship some improvements for this until the release in September.

Xcode Previews

Albeit not being a direct feature of SwiftUI, a new feature called Xcode Previews ships with Xcode 11. It is essentially is a simulator directly integrated into an Xcode canvas which can be populated with views directly from code. This enables much faster iterations than the current simulator workflow as well as a more straightforward method to test different variations such as screen size, dark theme, dynamic type and many more. The best thing about Xcode Previews is that they are working with UIKit and AppKit views as well, as long as your views are conforming to ViewRepresentable.

The only recommendation I have for previews is that they benefit massively from a modularized application since for displaying the initial views it has to compile the module of the swift file as well as its dependencies. Incremental changes afterwards are fast since it makes use of the new dynamic replacement feature in Swift, but the first initial rendering will profit a lot from shorter compilation time.

Goodbye Cocoapods and Carthage

Well, not so fast there! Even though we finally got Swift package manager support in Xcode, which is awesome, there are still some crucial pieces missing to replace all the functionality Cocoapods and Carthage developed over the past years. However, first, let’s appreciate a moment how smooth the integration into Xcode for Swift packages is. You can easily integrate external dependencies via a URL to a repository or browse packages on GitHub from within Xcode. Furthermore, there is out-of-the-box support for local packages. The best about all of this is that files from packages are not referenced anymore in your .xcodeproj, which means no more merge conflicts for these parts of your apps in the project file 🎉 🎉 🎉. However, I want to quickly outline three shortcomings of the Swift package integration into Xcode and potential workarounds.

One of the still missing features of Swift package manager is that it doesn’t support resources so far. That means no assets, xibs, storyboards, etc. in these packages. This limits what third-party framework authors can do in their packages and makes it impossible for some of the current frameworks to support SwiftPM. However, for local dependencies, you can still work around this by creating a bundle which contains all the resources and access that bundle’s content from code in your package.

Another catch in the integration of Swift packages in Xcode is that everything is producing static libraries and is therefore statically linked. Albeit Apple’s recommendation to link dependencies statically over the past years in order to reduce app startup time, there are some cases where a dynamic framework is the better choice. In fact, when you are moving your dependencies to packages you have to make sure that they are only used by one dynamic target or application otherwise you will end up with duplicated symbols during runtime and it will result in unexpected behaviours. After talking with Apple engineers at the conference and bringing this up, they told us that they are aware of this and are planning to implement some smart logic inside the build system which chooses the appropriate linking strategy depending on the dependency graph. Gladly, until then there is an easy workaround by just wrapping the package dependency into a dynamic framework which has an @_exported import DependencyName and links against the package. This way you can use the package from multiple other dynamic frameworks without having duplicated symbols.

Additionally, binary packages are not yet supported by SwiftPM. This is currently a widely adopted feature from the current package managers which allows vendors to distribute their pre-built or closed-source frameworks. Many of the big framework vendors such as Google make use of this and until this is supported by SwiftPM there won’t be a full adoption. At the same time of writing this post, a couple of community members and I are working on a proposal to add support for integrating vendored binary dependencies to SwiftPM. We hope to get the proposal out soon for feedback.

To sum it up

This year WWDC was filled up with so many great things that it is hard to cover all of them in one post. With Combine and SwiftUI we are at the verge of entirely new ways to develop applications on Apple platforms. On the other hand, the integration of Swift packages into Xcode will change the way we structure and split our projects.

Altogether, in the Sixt mobile team we are so happy about everything that came out this year and seeing these multi-year investments from Apple finally paying off. We can’t wait to see what everybody is doing with the new tools and are excited to adopt the new technologies in our applications as soon as we can.

--

--