Apple's inability to deploy a new UI framework that's better than the previous one is troubling. This is the company that shifted from Toolbox to Carbon to Cocoa and each step was better than the last. Could Apple build MacOS X and Cocoa today if they didn't already exist? Microsoft's two decades of failure to ship a true successor to Win32 suggests that Microsoft (at least, the operating system side of the company) died a long time ago. I wonder if we'll say the same thing about Apple 10 years hence.
But I feel like Apple wanted to appeal to young web devs and tried to offer something more similar to what these are used to.
I sure hope they can figure out a way through. Whatever it is, SwiftUI isn't it.
I think this opinion is heavily shared by Swift developers now, but the messaging every WWDC is always "Swift and SwiftUI is the best way to build apps for Apple Platforms", etc.. If you have to keep telling everyone what they don't believe is true, it's a sign there's a problem.
It feels like someone with a lot of organizational power is disconnected from the pulse of the community. SwiftUI is undeniably clean in a lot of ways, it presents beautifully and fits on slides well, but that matters less and less, and this all wasn't really working out even before LLMs disrupted things.
It’s easy to say they were just trying to be trendy and thus the real flaw was the trend is bad and the fault of worse devs than us (the young web devs mentioned)
The thing that obviates that is the trendy stuff works, yet, SwiftUI doesn’t.
(source: I wrote ObjC/Cocoa as early as 2006, and switched to Flutter as my primary dev kit some years ago: it simply doesn’t have the performance issues mentioned.)
React works well, because it's only an abstraction over the real DOM. React only handles your app state. But the DOM mechanism is still very performant and very much imperative. But I don't think something like React would work well in a mobile app, because the UI tree is often very simple on iOS and macOS.
UI is also very much not functional, and in fact the lack of progress in UI the last 30-40 years can largely be traced to trying to create UI with procedural/functional programming languages, an instance of linguistic-architectural mismatch.
Further reading:
Programs = Data + Algorithms + Architecture: Consequences for Interactive Software Engineering -- Stéphane Chatty.
https://link.springer.com/chapter/10.1007/978-3-540-92698-6_...
Can Programmers Escape the Gentle Tyranny of call/return?
https://2020.programming-conference.org/details/salon-2020-p...
UIs Are Not Pure Functions of the Model - React.js and Cocoa Side by Side
https://blog.metaobject.com/2018/12/uis-are-not-pure-functio...
Beyond Procedure Calls as Component Glue: Connectors Deserve Metaclass Status
https://2024.splashcon.org/details/splash-2024-Onward-papers...
What is your thesis then? What is UI?
Unfortunately when complex state transitions, async, and virtualization enters the discussion, the magic of React breaks, and you have to deal with all that, and also deal with how React's engine handles things under the hood.
It's always going to be slower than using something imperative. Trying to process the entire world's state for the sake of purity can feel elegant but it isn't free. And the complexity that gets added to make things performant is worse than just accepting that UIs are going to require you to jump around the tree and modify state.
Every time I go through the trouble of understanding the latest web technique (React, Elm, Signals (the newest solution), etc.) to deal with state management and the DOM, I end up walking away disappointed. There's nothing new in them that you can use to improve what we've been doing for ages in native GUI toolkits.
And to jump back to the original topic, yes, Cocoa was pretty decent, and SwiftUI while nice in many ways tries to Reactify native macOS development and made it worse. And it made Swift incredibly more complex and worse in hindsight.
1. The UI tells the model to change.
2. The model does the change and possible related changes.
3. The model notifies the UI that something has changed.
4. The UI updates itself from the model.
Alas almost nobody does MVC, despite calling what they do MVC.
I didn't say that.
User interfaces representation are mostly trees. And with functional programming you basically have Tree2 = f(Tree1). Until f is done you can't do anything really. React has a lot of escape hatches to improve performance, but they are escape hatches, not an endorsement of the architecture.
With imperative programming (and OOP), you only have that single `Tree`, which you update at will. Less elegant yes, but we have modularization to help us there. What Emacs does is to keep that `Tree` as a single mutable object, but have the code be functional, while the results are imperative.
I’m no huge apple fan, but I didn’t really think the 17 was more than a regular boring spec upgrade, which seems fine all things considered. (Currently on an iPhone fucking 17)
Data Flow: The author claims there’s no way to know when things update. Not only does experience help here but there are profile tools that tell you when and where things are updated. This isn’t black magic. Keep Views small, be careful how you hand around data. @environment is super cool but can have a cascade effect. This was greatly improved iOS 17+ and I wouldn’t support anything older than iOS 17.
GeometryReader: Occasionally I’ll use this. It’s kind of a necessary evil when dealing with certain view complexity. It can also be a sign that you’re doing something wrong.
API Stability and performance: Apple users upgrade. There’s no reason that you should be supporting iOS 17 at this point — even iOS 18 is roughly 2%% of our user base across several apps. I’ve been using SwiftUI without major performance issues but I also don’t early optimize. I profile and fix as needed. One of the early studios I worked for wrote all our games in UIKit as prototypes, when performance tanked we’d switch to the appropriate tools (eg. OpenGL) where it was necessary — like in the core game.
I could go on but in the end just use the right tool for the job, if you’re not proficient in SwiftUI or it isn’t going to work for your cross platform project, you have a lot of other alternatives. For me though, it’s been amazing to work with. I stepped away from iOS programming for 3 - 4 years because I was burnt out using storyboards, dealing with massive view controllers, and all the boiler plate it’d take to get a view up and going in UIKit. SwiftUI roped me back in.
* Quick addition edit: Cross platform for iOS, iPad, macOS has never been good. I’ve found recent updates have made things better to the point of tolerable and it’s nothing like when we had to post-fix an ~ipad to our Nibs — There has never been a ‘glory days’ of cross platform Apple UI libraries.
These frameworks have a number of good ideas but they don't necessarily combine in a way that transcends high quality traditional imperative frameworks with declarative-reactive bits sprinkled throughout, at least for more complex apps. SwiftUI and its ilk work best for super simple tabs-and-flat-lists sorts of apps.
In my experience the solution is often to use the appropriate architecture underneath your UI layer. Basically you build a data structure that represents your UI and always hand this entire structure to the declarative UI layer. Underneath the UI layer, you can still use imperative code to manipulate the data structures. The benefit of the reactive/declarative approach is that you don't have to think about how changes in the data need to be reflected in the UI. That's the framework's job.
Note: With "data structure" I don't mean "build a shadow DOM". I mean something specialized to your use case.
In SwiftUI, that means endless chains of modifiers, and in Compose this means monstrous constructors and modifier chains. Both get really ugly and painful to read quickly, and there's not a lot that can be done about it apart from breaking everything out into smaller views (which only goes so far). The amount of boilerplate saved isn't worth the trade, in my opinion.
In an imperative setup, there's still a lot of code but there are more options for organization, readability, and overall clarity. One can break things up with comments, break out setup into functions with self-explanatory names (that the IDE can then quick jump to, as a bonus), etc.
Yes, it's easier to get tripped up with imperative frameworks if one isn't thoughtful with managing their data, but much of the time that code only needs to be gotten right once.
And because of the open source nature you can always drop down in layers, just a few weeks ago I made a very specific engine optimization, all while the application code on-top can stay declarative!
It also doesn't fix problems inherent to declarative UI, like readability breaking down easily and certain things that would be a cinch in an imperative framework being extremely awkward to implement.
The boundaries aren’t perfectly clean, and that’s fine. But the separation gives you a useful way to think: structure this first, style it later, add behaviour where needed.
My experience with Compose—though I suspect SwiftUI people will recognise the feeling—is that I have to think about everything, everywhere, all the time.
Then we add some MVVM/UDF flavour. The "ViewModel" knows nothing about the view, despite usually serving exactly one screen. Add some "MutableStateFlow"s, combine them into "ScreenUiState", expose it as a "StateFlow", collect it with lifecycle awareness.
Beautifully decoupled. Extremely testable.
Then the organisation writes no unit tests and relies entirely on two-hour nightly screen tests.
A welcome-page refactor breaks the profile page.
“Didn’t you check the nightly build?”
No. It runs at night.
“Well, that’s your responsibility.”
But you broke it.
“Yes, but it’s your code.”
Then why did we ship it?
Fine. Schedule the postmortem with my mother.
And I’m not blaming mobile developers here. I’m frontend, backend, full-stack, I think AI engineer now. I have personally helped make simple things complicated across the entire stack.
What I like about the web is that one simple screen can be vanilla JavaScript. Another can use Vue. Another can use some specialised spreadsheet component.
People react to that with horror: what if components are duplicated, behave or look slightly different?
Fair concern. But that is real coupling with visible consequences and trade-offs. Somehow we have started treating coupling as something abstract that only exists inside code, rather than something that should produce an actual benefit when removed.
HTML. CSS. JavaScript. Or something close to it.
Maybe I’m getting old.
Just MHO, and it’s not going to stop the juggernaut, but there’s just no appeal in moving there for me :( If (when ?) Apple drop ObjC, that’s the day I move to Linux
Unfortunately although Swift seemed promising at first, by the time Swift 3 rolled around a lot of people were actively frustrated and moved on from iOS development. Having actual experienced hands guiding that ship could have led to something great instead of the mess that is there today.
SwiftUI is a laudable attempt to idiot-proof UI, but it sacrifices too much and ultimately fails.
But now I feel like for most apps, I should be fine with Compose Multiplatform and Kotlin Multiplatform. I don't see the point of learning SwiftUI anymore.
I think this is true. SwiftUI became "very good" as of iOS 26 (in part because the performance gap mostly evaporated) and continues to get better in iOS 27. Over and over, I see UIKit developers trying to do things "the UIKit way" in SwiftUI, and they'd rather write TFAs instead of considering that they may need to skill up and learn to write effective and idiomatic SwiftUI.
Personally, SwiftUI makes the 80% so much easier that, even if the remaining 20% requires dropping down to UIKit, it's worth it.
What does this even mean? There are hundreds of thousands of apps in the App Store that are 100% SwiftUI. They are real. And they are very much "production grade".
The only people still complaining about SwiftUI 7 years later are the UIKit holdouts that never took the time to properly learn how to use it.
WPF is still around and have been spruced up as of late.
UWP was the DOA Windows 8/8.1/10 app format that was super restrictive, strange to develop for, and non-portable. It's basically MS's equivalent of SwiftUI.
Apple has at least been consistent on UI frameworks.
Back when I wanted WPF to succeed, Microsoft was barely using it in any of their own apps.
Apple has used SwiftUI in their OS more than MS/Windows did, and there's quite a few apps on the App Store that -seem- to be made with SwiftUI.
I went through Visual Basic, .NET, WPF, Cocoa, and other random frameworks all professing to be the promised panacea for UI, but I think SwiftUI+SwiftData is the best environment ever.. IF only it could reach its full potential, i.e. do everything that Apple's "legacy" APIs can do.
I even tried using SwiftUI for games: https://i.imgur.com/5aTWbft.mp4
The biggest/worst hurdle in the "modern" dev experience is Apple's insistence on a yearly update cycle and the way they advertise those updates: You have to wait for the next WWDC and suffer through videos of uncanny-valley presenters, hoping to catch a glimpse of something that fixes the shit that was bothering you since the last WWDC.
3rd-party sites like hackingwithswift.com & swiftwithmajid.com provide invaluable info that Apple's own docs should.
At least the Swift language has been getting more regular updates since it went open source.
There's no way I'd dare to take on a full Apple-platform app project alone on my own, but I've started dabbling in it again thanks to AI: Codex even converted an old app I made in Visual Basic 900 years ago and had it running in SwiftUI within minutes!
I've even tried to get AI to sift through the WWDC video transcripts so I won't have to waste my mortal lifespan on that.
And that's really sad, because earlier Mac OS X (and even OPENSTEP to a degree) was an Eldorado for boutique developers, not least due to frameworks like Cocoa and Objective-C (despite all the hate it seems to get).
If you knew C, it was not hard to grasp Objective-C (at least it was much easier than say C++ and MFC on the Windows side of things).
My first Apple purchase was an iPad I got for my aunt, and I loved how streamlined yet powerful it was so I installed a VM on Windows to dabble in iOS development, and fell in love with the sheer consistency of macOS, iOS and their APIs.
This was during the era when Microsoft was still figuring out whether to keep the Start Menu and replace the whole Windows UX with a tablet UI, so it was an easy jump.
Almost never looked back, and whenever I do I'm glad I jumped.
Then came Swift and I loved it, but then it took literal years to catch up with everything you could do in Objective-C with the Apple APIs. SwiftUI is having the same problem but for much longer :(
It is a newbie trap. It is great at producing simple apps, or things that don't require intense scrolling, or anything with heavy animations and precise layouts, but when you do something smooth, it is not it. It feels more of a React Native competitor, than a true UIKit replacement.
Also, almost everything that Apple has re-wrote with SwiftUI, came out worse as before (Settings, Spotlight, etc), and that doesn't help.
With AI coding... SwiftUI lost its edge/advantage (easy to layout screens), as now you code less of that directly, and might as well just go fo the framework that allows the most flexibility and gives you the best results for your users.
Apple really needs to either double down on it, and make it such that it has everything that UIKit has (match both features and performance), or just turn it into another optional framework, just as Interface Builder (.xib files) back in the day of Objective-C.
Right now it heavily promotes it as a first class citizen, meanwhile the features are not even parity with UIKit. It is so misleading to newcomers to the platform.
Ps. The other upsetting thing about SwiftUI, is that it has hurt the Swift language as well, as the team has had to introduce all kinds of hacks, or obscure features to the language in order to make it work, which made even the Swift language experience worse and more complicated than it should have been.
On the contrary, I think AI has made it EASIER to approach SwiftUI now, because AI makes up for SwiftUI's biggest weaknesses: the many ways of doing everything, Apple's wonky documentation and the need to know when to fall back to AppKit/UIKit.
In car terms:
UIKit - Manual Transmission - you control everything, but a bit of a chore
SwiftUI - Slushbox Auto Transmission - easier to drive, sucks for performance
UIKIT+AI Coding - Dual Clutch Transmission - both great performance, and easy to control/drive
That is, pure native apps, can integrate KMP libraries. They cannot integrate Flutter libraries.
In other words, if I write a KMP library, I can ship it for multiple platforms and developers can use it in their Flutter project, or in their pure Android/Kotlin project, or in their pure iOS project.
SwiftUI is good, albeit not without issues, as long as you tolerate them. The same is true for any approach. My most recent app was built in SwiftUI because I have been using React Native in my professional work for so long I wanted a change of scenery.
Each approach has its issues, and it all boils down to a matter of preference and which tradeoffs are appropriate for the project.
All that to say, I don't think that vibe-porting will give you more than cross-platform. With cross-platform, at least your engineers understand the codebase.
If KDE can develop a high performance stable desktop, you can design whatever.
I don't know what your experience is, and I mean no offence or anything, but the only people I have seen who were happy with Qt for mobile development were people who had never tried to do it with a modern language, like Kotlin.
With Compose Multiplatform and Kotlin Multiplatform, you can write a cross-platform app in a modern language, and that is far better than C++.
1. It uses the builder pattern for views (familiar to those who used Java) but for some reason they decided to make it so that the order of the modifiers in the builder matters. Each modifier doesn't actually modify the main view but it modifies what the modifier before it decided to return. This makes no sense as the modifiers should each be modifying the main view to make everything predictable and easy to debug. I'm convinced no one (not even senior devs with 5 years of SwiftUI experience) understands how the ordering of modifiers works. It's just swap them until it does what you want it to.
2. The view lifecycles and code execution path seem random and hidden behind layers of "magic," making it incredibly difficult for developers to trace and debug issues.
3. It is practically impossible to set breakpoints for rendering and view construction, it's impossible to really figure out when re-renders happen and what drives them. I'm convinced SwiftUI apps are incredibly slow not because the SwiftUI implementation itself is slow, it's because, even Apple's own apps probably do a bunch of unnecessary re-renders and one no one seems to have any idea. This is unfortunately another design issue that can't be solved by just making SwiftUI more efficient. It requires simplification and tooling to help developers not footgun themselves.
4. Lots of issues start appearing later on in the development cycle because, for simple apps, bad SwiftUI design decisions and footguns have unnoticeable effects, until the apps gets more complex and things start breaking. Fixing these issues sometimes requires rewriting whole features or spending hours debugging.
5. There seems to be almost no documentation on Liquid Glass. It's laughable that after more than 1 year, Apple has simply refused to document or provide good examples for Liquid Glass, except for maybe couple pages that resemble the brain dump of an engineer that has never passed a writing class in college?
6. Stuff seems to be rapidly changing and breaking from version to version. It took days to make my app look and work the same in iOS 27 as it did on iOS 26, even though iOS 27 is supposed to be a minor bug fix release. We don't even use anything non-standard and don't do any hacks. This defeats the whole purpose of a simple UI framework that can be easily adopted to different platforms (this never used to happen with UIKit).
7. View debugger still has no SwiftUI equivalent. It used to make things so much simpler in UIKit when you could just see the view bounds, pick views apart and understand what's actually happening. SwiftUI has no equivalent other than `.background(.red)`. Terrible.
I don't know how Apple can salvage this beyond just undoing some of these terrible design decisions and making it 1. super simple to work with, 2. stop relying on magic, making things more explicit, and 3. providing actual 1:1 UIKit feature parity.
2. There’s no magic here. There is poor documentation. The biggest trick — small views, think about what values are going to trigger a refresh. Avoid cascading view refreshes.
6. You might have missed a couple big iOS releases (iOS 7 was one to remember) where many of our apps fell over in UIKit. Swift was another ‘DOA’ for YEARS with the same issues you’re making here, each new version broke the old, but here we are in a day and age where it’s the standard.
2. Documentation issue. The lifecycle is standardized, but Apple is terrible as documenting it all in one place. I found this year's "Dive into lazy stacks and scrolling with SwiftUI" WWDC video actually had a pretty good explanation, at least for the lifecycle within lazy containers.
3 and 7. Yes, Apple's tools suck pretty bad. Preview canvas is also still terrible, despite multiple attempts to improve.
4. Not something I've experienced, not sure what you mean.
5. Yeah, Apple's docs suck.
6. Not sure what you mean here either, our stuff looks pretty much the same.
You mention some examples, I have experience with lower-level stuff: terrible. Poorly documented, and actually not really working well.
IMO they should focus on improving the developer experience instead of wasting money on the joke that is Liquid Glass (even users don't like it, right?). But anyway, too late for me: I'm soooo happy that I can develop iOS apps in Kotlin now, and just endure Xcode for building and occasional debugging.
In my professional medical opinion, he is at high risk of being replaced by a year old low-end Chinese open source LLM.
He is brute forcing his way through life and broadcasting it on YouTube.
Dunno man, Xogot is made up of almost half a million lines of code. Of those 727 files use SwiftUI, and 65 use UIKit, 119 use AppKit (I did not count the overlap, so they are not mutually exclusive).
Using GeometryReader makes it clear he is living in the past and the fact that he uses printChanges in this year without mentioning the dedicated SwiftUI instrument show a lack of curiosity on the space.