SwiftUI at WWDC 2025
Learn what’s new in SwiftUI to build great apps for any Apple platform. We’ll explore how to give your app a brand new look and feel with Liquid Glass. Discover how to boost performance with framework enhancements and new instruments, and integrate advanced capabilities like web content and rich text editing. We’ll also show you how SwiftUI is expanding to more places, including laying out views in three dimensions.
Is list/table performance actually fixed? The quoted 6x (loading) and 16x (updating) improvements sound good but don’t seem like enough to match NSTableView
. The session cites improved scheduling and lazy loading rather than an architectural change. Maybe that’s not possible without changing the API.
Optimize SwiftUI performance with Instruments:
Discover the new SwiftUI instrument. We’ll cover how SwiftUI updates views, how changes in your app’s data affect those updates, and how the new instrument helps you visualize those causes and effects. To get the most out of this session, we recommend being familiar with writing apps in SwiftUI.
Explore concurrency in SwiftUI:
Discover how SwiftUI leverages Swift concurrency to build safe and responsive apps. Explore how SwiftUI uses the main actor by default and offloads work to other actors. Learn how to interpret concurrency annotations and manage async tasks with SwiftUI’s event loop for smooth animations and UI updates. You’ll leave knowing how to avoid data races and write code fearlessly.
Build a SwiftUI app with the new design:
Explore the ways Liquid Glass transforms the look and feel of your app. Discover how this stunning new material enhances toolbars, controls, and app structures across platforms, providing delightful interactions and seamlessly integrating your app with the system. Learn how to adopt new APIs that can help you make the most of Liquid Glass.
Discover how you can use WebKit to effortlessly integrate web content into your SwiftUI apps. Learn how to load and display web content, communicate with webpages, and more.
SwiftUI’s performance does seem to be pretty good on iOS 26, at least on the simulator. Seems that all of the table view issues I had with BurnoutBuddy are now gone!
So AppKit controls are now just wrappers on some custom/private SwiftUI views on macOS 26 Tahoe?
After the 6 years that has passed since SwiftUI was first announced, we finally get a native WebView, with some additional web-related tools.
So this is new in #SwiftUI! In AppKit, it was a paaaaaain to have your Settings window animate from tab to tab based on the view’s content. Some developers (even Apple) wouldn’t bother to do it in some apps.
SwiftUI has a modifier for resizing the window based on the content of the view for the selected tab!
WWDC25 seems like the least pushy re SwiftUI so far. It seems much more like ‘just another technology’ that you can use in your apps, as it should be, rather than the only way you should be making things.
All of the new UI across the platforms is built with and available to UIKit & AppKit (even if there may be sprinklings of SwiftUI under the hood), and a number of barriers that pushed you to SwiftUI before (like on visionOS) are now open to UIKit.
Seems much healthier!
I don’t know if this is just a temporary pause in messaging, or if the practical realities of SwiftUI have set in now that we’re six years in. It’s great for some things, but it’s not great for everything, and you will always be served well by having a bigger, better, more-powerful framework underneath — whatever that may be in the future
I always used to say SwiftUI unless your app needed long form text editing or a list/table with lots of data. With this year’s updates, I’m not sure about either of those limitations, so SwiftUI gets my vote.
Remember when SwiftUI launched and we all pretended it was production-ready, and it was. And now it’s been 26 years (but more like five) of SwiftUI and it’s better than ever.
While navigation stacks API didn’t change, the tab navigation provides us with a few new APIs allowing us to improve user experience respecting the new design language. If you still use old TabView APIs, it is a perfect time to refactor your tab navigation. While old APIs also get glassy transformations, the new ones allow us to craft them much better.
Now that you’ve seen everything from SwiftUI 26, what is still missing? What are the key pain points you hit?
Interaction of drag gestures and scroll view (that I need for scroll/long press and drag to scrub charts in @weathergraph - see below) is still bugridden and requires ugly hacks, some of them even OS version specific.
Previously:
- Showing Settings From macOS Menu Bar Items
- WWDC 2025 Links
- SwiftUI at WWDC24
- NSTableView With SwiftUI
- SwiftUI Performance Gotchas
Update (2025-06-19): Gwendal Roué:
Last time I checked (a few years ago),
List
was requiring a SwiftCollection
, which means that all elements must pre-exist (there is no support for lazily loading data on demand). This requires an API change.
List
was iterating all elements in the collection, upfront, even those which are far off-screen, for some reason, ruining the performance. But that looks like a fixable problem (maybe fixed already).Nothing beats the performance of fixed-height rows, and that also requires an API change. Apps should be able to better support SwiftUI for computation/caching of element dimensions. Now this is really not trivial:
IndexPath
is gone, so we are no longer able to deal with plain and fast integers. Instead, elements are identified by their ID. Computing hashes is really frustrating when you want to deal with indexes for raw performance.
Update (2025-07-07): Joseph Smith:
UIKit:
- You write a lot of code, but you know what its doing
- You’re “in control”, even if its verbose
SwiftUI:
- You write little code… until it breaks
- You rely on a magic state machine that works until it doesn’t
- Fixing one line bugs sometimes means rearchitecting the view tree
7 Comments RSS · Twitter · Mastodon
> Now that you’ve seen everything from SwiftUI 26, what is still missing? What are the key pain points you hit?
Taste? Usability? Good UI/UX guidelines used by the system vendor itself?
> So this is new in #SwiftUI! In AppKit, it was a paaaaaain to have your Settings window animate from tab to tab based on the view’s content.
It was? Wtf. I always use NSWindowController and that’s easy enough for me…but didn’t Apple make a view controller API in Yosemite like NSTabViewControllerTabStyleToolbar…so…animate the window frame when a tab selection is made is hard? I must be the crazy one.
Apparently the SwiftUI implementation isn’t working yet in the beta..I’m sure they’ll fix it before it’s released. Yea they’ll definitely fix it…I mean they have to fix it, right…they always do.
—-
> I don’t know if this is just a temporary pause in messaging, or if the practical realities of SwiftUI have set in now that we’re six years in
Reimplementing AppKit controls in SwiftUI under the covers doesn’t seem like a pause in anything. I expect Appkit apps to inherit SwiftUI bugs. They’re spreading the poison everywhere.
I mean it’s going to be the dev community’s fault ultimately. Not enough people are giving Apple pushback and are celebrating basic improvements as “game changing”. We’re going to get what we deserve
@ObjC4Life NSTabViewControllerTabStyleToolbar
makes it easier, but you still have to remember the sizes of each tab and set up the transition animation. My code is also manually setting the window size when the tab changes. I see that some people are getting that automatically by setting each tab’s preferredContentSize
. Maybe I didn’t do that because it doesn’t work with animation or some other bug at the time…I don’t recall.
At best i’d say it’s a minor annoyance and SwiftUI will inflict way more pain than sizing a Preferences window in AppKit in other areas. If this SwiftUI bit is a “win” it’s a very small one.
SwiftUI being good for preferences seems to be a reoccurring topic which is kind of ironic since it was used to produce System Settings app, and now Xcode Settings. Apple leading by example..leading us off a cliff
There are plenty of ways Apple could make preferences easier in Appkit if this was so bad… like introducing an API like i did for myself. Something like:
NSPreferencesViewController
-initWithPreferencesDict:toolbarIcon:
-initWithPlistURL:toolbarIcon:
Which reads a plist and creates ui based on the preference types in the plist. Radio group buttons for radio preferences, etc.
And dictionary entry for custom button title that opens a sheet..no ios style navigation controllers on mac.
Also could have an api for custom UI where stock doesn’t cut it:
-initWithContentViewContriller: // embeds your custom setting view controller inside
Any ui you want.
Then NSPreferencesWindowController:
-initWithViewControllers:preferenceViewControllers]
Show the preferences window controller, each view controller is a tab. Window controller sizes itself on tab selection. KVOs preferredContentSize on view controllers and resizes the window if it changes for the current selected tab.
Then 99% of preferences done with almost no code outside of the framework usually just 4-5 plist files.
Apple has an implementation like this in Catalyst but of course they didn’t take it far enough and didn’t finish. Too busy writing shitty preference UIs in their shitty tinker toy ui framework. Got developers running on a treadmill
@Anonymous Yeah, there are tons of places where AppKit could have some common controllers to help you hook things together and implement common patterns, but Apple seems to have lost interest in that after Cocoa Bindings.
> Now this is really not trivial: IndexPath is gone, so we are no longer able to deal with plain and fast integers. Nothing beats the performance of fixed-height rows, and that also requires an API change. Apps should be able to better support SwiftUI for computation/caching of element dimensions.
Yea this is true in UIKit as well..diffable data sources makes certain things easier, but it's as if Apple doesn't think developers would ever need to display thousands of rows. There is no API to simplify paging in data or creating placeholder rows while content is being loaded. Placeholder rows require a unique identifier in a diffable data source. So instead of just returning the row count and storing the fact that rows >= 5000 are placeholders which would get loaded in on scroll, you actually need to create unique objects for every single placeholder. This is why I don't use diffable datasources when there could potentially be thousands of rows of user data.
It's easy enough to handle this on down scroll. Just don't return a larger row count than what's in memory and load in more rows when the user gets to the bottom. But on up scroll if you remove rows rather than using placeholders you break the illusion because the scroll bar position will jump around. I think you can try to fight UIKit and set the scroll bar position yourself but it's not so easy if row height is computed dynamically.