Technical

/
Opinion

Making a Mac app in SwiftUI? Reach for AppKit.

How Apple has treated its shiny new toolkit as a second-class citizen

Is the Shortcuts app written in AppKit or SwiftUI?

No beating around the bush: You can’t make a good native Mac app in pure SwiftUI.

It’s not that I dislike SwiftUI. Admittedly I was hesitant when Jetpack Compose first came out, but today I can’t imagine writing an Android app in anything but.

I love SwiftUI, possibly even more than Jetpack Compose - unique features like two-way bindings and environment objects make tasks that are possible in other frameworks a breeze in SwiftUI.

That being said, in my years of using it, it’s become painstakingly obvious that apps written in pure SwiftUI result in a worse experience for both the developer and the user. Using them feels like an afterthought, rather than a beautifully-crafted experience like Mac apps from the past.

Turning System Settings off the right track

With the release of macOS 13 Ventura, Apple completely redid the System Settings app, formerly known as System Preferences.

This was met with a lot of criticism: buggy layouts, keyboard shortcuts not working, and a cramped but clunkier design that feels like it was ripped right from iOS.

Why did Apple do this? If you take a look at how the app was built, you’ll see it’s running on SwiftUI. Many people believe Apple deliberately did this to showcase how effective SwiftUI can be, when in fact it turns out that it did quite the opposite.

As I write this on macOS 14 Sonoma, I’ll give Apple credit that System Settings is certainly less buggy. But whenever I open it up, I still get the sensation that this was not designed for a large screen and a mouse.

System Settings on macOS 14

The sidebar on the left used to be one screen, but was changed to mirror iOS / iPadOS

This is not only because of the constraints of the newer SwiftUI framework itself, but also through Apple pushing their ideologies through their new tools.

A Catalyst to the iOS-ification of macOS

Mac Catalyst is a technology Apple created that lets users port their iPad apps directly to macOS with minimal changes.

Quickly after, many of Apple’s own apps were ported using this technology, such as Voice Memos and Home.

Voice Memos on macOS 14

Use this app for 5 seconds, and you’ll find it’s very clear that this is not a Mac app.

For reference, here’s what a well-designed Mac app looks like:

Voice Memos on macOS 14

It should be clear why using Mac Catalyst is not a good option for making a Mac app. But what does this have to do with SwiftUI?

These cross-platform technologies must fulfill the most common materialization of Apple’s design language. And of course, that is iOS.

Even Apple doesn’t use SwiftUI where it matters.

(other than System Settings)

Of course, many of Apple’s Mac apps that have been around for a while stick completely with AppKit, like Finder or Safari, likely because they would require too much effort to rewrite.

However, with many of Apple’s newer apps they go for a hybrid approach, where the parts of the app that need to feel the most macOS-y are written in AppKit, and everything else in SwiftUI.

The Shortcuts app uses this approach:

A diagram of the Shortcuts app that shows which parts are written in AppKit or SwiftUI

Using SwiftUI responsibly

SwiftUI is still an amazing technology, and I think many people will agree that it’s easier to use than AppKit by a long shot.

However, macOS has had a long and rich history, and evolved its own unique interaction paradigms. In spite of SwiftUI being cross-platform, Apple’s interests are clearly more focused on iOS. For us macOS developers who are looking to make amazing Mac apps, it means that we need to know when to use it and when not to.

Many app features like toolbars with split window toolbars, inspector panels, or custom text editors are difficult or impossible to achieve with SwiftUI. I ran into all three of these issues in one of my own apps, and ended up rewriting most of the UI in AppKit.

A diagram of one of my apps that shows which parts are written in AppKit or SwiftUI

Going forward, I will continue to develop Mac apps in AppKit first, and only reach for SwiftUI when I know its limitations won’t get in the way.

I love SwiftUI for prototyping and throwaway projects, but for the apps that I want to leave an impression, I’ll stick with AppKit. Though with SwiftUI receiving updates every year, I hope that someday it will be the opposite.