With the start of WWDC21 just around the corner, I’d like to continue the tradition that I started in 2019, and share some of my biggest hopes and dreams for this year’s edition of the conference.
Note that these are really not predictions, nor are they based on any kind of insider information. It’s just me sharing some of my personal Swift-related WWDC dreams with you.
I absolutely love SwiftUI (so much so that I’m kind of porting it to the web), but that doesn’t mean that it’s perfect. In fact, being just shy of two years old at this point, it’s still a very young framework that has yet to become as feature-complete, flexible and powerful as tools like UIKit and AppKit are.
One of the key improvements that I’d like to see this year — that would unlock a lot of that additional power and flexibility — is for Apple to add proper, fully baked customization APIs to the entire suite of system views that the framework ships with.
For example, like we took a look at in “Encapsulating SwiftUI view styles”, the ButtonStyle
protocol already enables us to perform very custom, finely grained customization when it comes to how Button
views are styled:
struct ActionButtonStyle: ButtonStyle {
func makeBody(configuration: Configuration) -> some View {
configuration.label
.foregroundColor(.white)
.font(Font.body.bold())
.padding(10)
.padding(.horizontal, 20)
.background(Color.blue)
.cornerRadius(10)
}
}
What makes styles defined using the above protocol so powerful is that they can be applied to an entire view hierarchy at once — making it possible to very neatly separate an app’s styling and theming code from the specific logic that’s contained within each individual view. In fact, if we wanted to, we could even style all of the buttons within an entire SwiftUI-based application simply by doing this:
@main struct MyApp: App {
var body: some Scene {
WindowGroup {
RootView().buttonStyle(ActionButtonStyle())
}
}
}
However, while SwiftUI already ships with a number of other styling protocols that work the exact same way as ButtonStyle
, many of them are currently not available for us third-party developers to implement. Take the NavigationViewStyle
protocol, for example. If we take a look at its public definition by command-clicking it in Xcode, all that we’ll see is this:
public protocol NavigationViewStyle {
}
The same thing is true for other, similar protocols as well — including ListStyle
, MenuButtonStyle
, PickerStyle
, and so on. So, my wish would be for Apple to open up those protocols so that we’ll be able to write custom styles for more or less any built-in SwiftUI view, not just for a few select ones, like Button
and Label
. I think that could solve many of the styling-related issues that lots of developers (myself included) have faced when adopting SwiftUI within apps that require more custom-looking UIs.
For example, the above kind of customization APIs could enable us to style navigation and tab bars, to (finally) be able to remove list cell separators, and to perform other kinds of common tweaks that UIKit and AppKit make super simple, but SwiftUI currently makes close to impossible (without resorting to some form of UIAppearance
or subview hacking).
I think that SwiftUI already has a quite broad coverage when it comes to the types of views that it supports, so (at least from my perspective) it would make a ton of sense for Apple to instead focus on depth this year — to make the views that SwiftUI already offers much more flexible, powerful, and customizable.
With concurrency being such a strong focus of Swift 5.5 (which I’ll cover in much more detail once I’ve had a chance to use it to write proper production code), I’d love to see Apple update many of the asynchronous APIs that ship as part of their SDKs to take full advantage of features like async/await
.
For example, imagine being able to perform a URLSession
-based network call like this:
let response = try await URLSession.shared.dataTask(for: url)
Or to request push notification permissions like this:
let center = UNUserNotificationCenter.current()
let isAuthorized = try await center.requestAuthorization()
While Combine already enables us to perform many kinds of asynchronous tasks in really powerful ways, if Apple were to fully embrace Swift’s new first-class concurrency features, I think that would both serve as great examples for the community to follow, and would make it much easier for us to adopt those features within our own code as well.
Plus, those new APIs would very likely be purely additive to the existing ones, meaning that (just like when Combine was introduced) we’d be able to migrate to them piece-by-piece, at our own pace.
To say that iOS 14’s introduction of WidgetKit has turned out to be successful is almost an understatement — with the new home screen widgets reaching very widespread adoption, not just among developers and tech enthusiasts, but also within the wider iOS user base (in big part thanks to the incredible work by Widgetsmith creator David Smith, who I had the true pleasure of talking to on the podcast a while back).
However, in their current shape, widgets are quite limited in terms of what kinds of user interactions that they can accept — with deep links into the host application being the only real way to implement custom interaction logic. Now, I completely understand why Apple made that decision. After all, like Eliza Block explained when she was a guest on the podcast last year, a widget’s UI isn’t actually constantly running on the home screen, but is rather rendered by the system based on serialized snapshots that are stored on disk, mostly for performance and energy efficiency reasons.
So if the system is essentially rendering all widgets as completely static view hierarchies that are computed up-front (by a widget’s backing TimelineProvider
), how could Apple enable us to write custom interaction code within that context, without fundamentally changing the way widgets work?
One idea that comes to mind is that some form of event-based message-passing system could be introduced, that would enable a given widget’s timeline entry views to trigger custom events, for example using something like a built-in EventButton
:
struct ArticleWidgetEntryView: View {
var entry: ArticleEntry
var body: some View {
VStack(alignment: .leading, spacing: 5) {
Text(entry.article.title)
.bold()
Text(entry.article.description)
.foregroundColor(.secondary)
.font(.footnote)
EventButton(
systemImage: "heart.fill",
event: ArticleWidget.Event.toggleFavorite
)
}
.padding()
}
}
Since the above doesn’t involve executing any arbitrary view-level code in response to user interactions, it would still let the system remain in complete control over the rendering and lifecycle of all widget UIs.
Because WidgetKit is Swift(UI)-only, the above Event
type could then very likely be referenced by both the main Widget
definition, and its TimelineProvider
, in a completely type-safe way — rather than having to pass either raw strings or userInfo
-style dictionaries around.
For example, perhaps the TimelineProvider
protocol (or a specialized version of it) could gain a new method that would be passed any Event
that was triggered (as well as the entry that triggered it), which in turn would let us run completely custom code in response to that, while still enabling the system to keep using its snapshot-based rendering strategy.
Although the overall quality of Swift’s tooling and the way it’s integrated into Xcode has certainly improved since when the language was first introduced, it remains one of the most significant drawbacks of Swift as a whole. It’s still, in 2021, very common for autocomplete to completely stop working, for syntax highlighting to disappear, and for obscure error messages to be shown when a compilation failure occurred — even within relatively simple projects.
I realize that these are not easy problems to solve, especially given Swift’s overall complexity and very rapid evolution, but if I could just pick a single item from this list of dreams, then it’d be this one. There’s just so many things to like about Swift, UIKit, SwiftUI, and the rest of Apple’s frameworks and SDKs, and for all of its flaws, I think that Xcode is actually a quite fantastic development environment overall — I just really wish that the basic editing experience would get elevated to the very high level of quality that I’ve come to expect from Apple products.
That’s not to say that all of Swift’s tooling is flawed. Take the Swift Package Manager for example — overall, it’s by far the most stable and easy-to-use dependency management system that I’ve ever used (and I don’t mean that as an insult to any of the other package managers out there). Basically, when using SwiftPM, dependency management has mostly become a solved problem, at least for me and the teams that I work with. It’s fast, reliable, and powerful. The same thing can now also be said for Xcode’s new build system, and many other parts of the overall experience of developing apps for Apple’s platforms.
So, what I’m hoping for is for some of the rough edges to be smoothened out, and I’m sure that we’ll get there one day. Let’s see if Xcode 13’s release day will be that day.
Finally, I’d also still love to see some of my remaining 2020 dreams eventually become reality.
Xcode on iPad is something that I’ve long been wishing for. I know that not everyone wants to write code on an iPad, but I really do, especially when traveling or when working outside. That doesn’t mean that I’d stop using my M1 Mac mini if an iPad version of Xcode would be released next week — it would just mean that I’d have an additional device that I, and others, could build apps and libraries on.
Swift Playgrounds is an amazing tool for learning, prototyping and experimentation — but it’s not an IDE for building proper apps and Swift packages, and it was never intended to be. I think at this point in its lifecycle, the iPad should become a computing platform that’s not just capable of running apps — it should also enable us to build and deploy them.
End-to-end Swift, or some form of Swift-based cloud functions, was also one of my 2020 dreams. So many apps need to run server-side logic, but not all of them really need a completely custom server. Sure, there are lots of third-party tools available that lets us deploy individual pieces of logic, such as Cloudflare Workers (which is what powers this site’s search feature), but it would be incredible to see a completely integrated, Swift-based server-less system from Apple that would let us accomplish similar things.
I’d also still very much like to be able to use the Swift Package Manager to define entire app projects, rather than just libraries and command line tools. Like I mentioned earlier, SwiftPM is one of my favorite parts of Swift’s overall toolchain, so I’d be delighted to see it expand to cover even more use cases this year.
Those are my biggest Swift-related dreams for WWDC21. What do you think? Do you share some of my dreams, or are there any other Swift-related announcements that you’d like to see next week? Let me know via either Twitter or email.
If you enjoyed this article, then make sure to check out WWDC by Sundell & Friends, on which I and some of my friends will cover WWDC21 in great detail all throughout the week of the conference.
Thanks for reading!