The problem with complex systems is that you can be dead long before you realize you're dead. Things can continue to seem "pretty good" for a long time just from the inertia of past good decisions and built-up infrastructure. You see some fraying or cracks but everything looks fundamentally sound, until it isn't.
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.
7 Years of release on Swift UI, 12 years for Swift.
This isn't 7 years of development, but 7 - 12 years after release. And to most these past 7 - 12 years are an ongoing beta development. It is unfinished, unpolished with no end in sight. And I have been extremely critical since the beginning.
But the problem runs much much deeper. It isn't the technology that is the problem, not the devs who are making it. It is the person making the decision as to WHY this was allowed from the get go. WHY this was allowed to be released, or even before all that WHY resources for development of these ideas were allowed in the first place.
For every yes that are a thousand no. Instead a lot of Apple's software development can be summarised as resume or KPI bonus driven development. It is not as bad as Google and Microsoft, but it is clear Apple have this problem a well.
If you look back into Jobs era of Apple software, ( and not just software ) Apple manage to have done most things 2x better with half the resources. The whole Apple now is bloated. And yet everyone is chanting Craig Federighi all the way.
And it is funny because for the vast majority of these 7-12 years I was the only few on HN and Twitter that was extremely skeptical of it, to the point I gave up writing ( or ranting ) about it before majority Swift and Swift UI developers negative sentiment emerged.
And I have often asked the same question every single time, what if they just spend one fifth of the resources to iterate and improve C / Objective-C and Cocoa. All the resources on Swift and everything adjacent to it could have been better spent somewhere else.
I have high hope for John Ternus, hopefully he gets his political game right and manage to change course for Apple software somewhere down the line.
It only worked that way for Steve Jobs, because under him, as it was at NeXT as well, either you dedicate your life to the cause, or go work elsewhere.
My opinion is that good old UIKit based on MVC (Model-View-Controller) is simply excellent for building scalable, complex and performant UI's in traditional, compiled languages. The declarative, state-driven UI works wonderfully on the small keynote-demo scale but needs a specialized language to support it on the large scale. Otherwise you waste a LOT of time debugging.
And Swift is simply just not that language. Apple should have just invented a specialized UI DSL to support SwiftUI. And continued to support good old MVC first-class. Explicit Constraints, Lifecycle Clarity and Programmable Control make UIKit apps easier to debug and fix.
SwiftUI should cleanly extracted out its reactive framework as a standalone, public framework for non-UI or decoupled use-cases. That would have helped in fixing a lot of issues.
The underlying problem is the programming industry completely resisting learning the lessons of Objective-C because it doesn't like them. It didn't like them when NeXT tried selling it, and it doesn't like it now.
You can't have Cocoa without Obj-C, or at least a langauge and runtime with that philosophy.
Apple software has been on a clear decline for a seriously long time, and it's propped up almost entirely by them pulling off Apple Silicon combined with how Microsoft have somehow been even worse.
The problem with ObjC was mainly syntax, bolted on over many years on top of a C core. It was grown rather than designed, and it shows. But there's nothing wrong with the runtime.
Swift should have just been a much improved syntax over that same runtime. It would have avoided so many headaches. For one they wouldn't have made the awful decision to have return-type overloading and completely ruin the typechecker's performance in the process.
SwiftUI should have unapologetically been a convenient, reactive wrapper over UIKit and AppKit, rather than treating them as deprecated implementation details that devs nonetheless keep having to drop down into.
These decisions come down to ego, of wanting to do away with the old and carve out your own legacy separate from it. Nice if you want a promotion but not so nice if you're trying to make a long lasting ecosystem for developers to build upon.
At least Swift and SwiftUI have a reasonable interoperability story with the past. Can't say the same about Microsoft's graveyard of UI frameworks.
i love swift, but i can't help but feel the same... after all this time we still can't get good error messages or fast incremental compilation; it just feels like we are boiling the ocean to get largely the same features but handled by the compiler now instead of the runtime (which has a lot of value, but i feel theres a balance to be had there idk)
if they had really just done objective-c without the c like, the original moniker said...
It is a generation thing, all the folks that were able to ship those products are now retired, or approaching retirement, and apparently newer generations can only do Electron, React Native and co.
I fell in love with SwiftUI the day it was announced, but as a solo dev I still haven't been able to make a full app with it yet, mostly because of the lack of documentation, and the gaps where you still need to drop down to AppKit/UIKit.
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.
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.
P.S. Re: AI, I don't mean outright generating entire apps from a single sentence (except for conversions of private tools), but using AI to navigate Apple's obtuse documentation and edge-case APIs, i.e. "how to do this"
I'm sure many will disagree, but I have doubts that pure declarative-reactive is the "right" shape for an all-purpose native UI framework. In my experience, Kotlin+Compose shares many of the same warts… its main redeeming quality is that it's better than Android Framework (most of the time), which is low bar to clear.
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.
I agree, the first section "Data Flow" reflects my concern with Compose as well:
> Data flow in SwiftUI is indeed reactive—but sometimes I wish it wasn’t, because it’s reactive in all the wrong ways. It often reacts to changes it should ignore, and it ignores the changes you actually care about. To me, SwiftUI’s reactivity is a black box: It makes achieving predictable behavior almost impossible.
In Compose, seeing rememberXXX(key1, key2) sprinkled all over with keys makes following the code difficult.
Then add some side effects like LifecycleEventEffect(Lifecycle.Event.ON_RESUME) { ... read permissions and render warning if we can't do something ... } and it becomes even more difficult to comprehend. Much of the Android framework APIs are not reactive, and polling on these UI events is still necessary (permission could have changed if the user put the app in the background, and you can't listen to them via Flow etc).
As the author says, these frameworks make the static data dependencies explicit but often at the expense of what is changing and why.
When I see rememberXXX(key1, key2) { } the first thing that comes to mind is, why would key1 and key2 change, and often that is not obvious.
To make complex layouts (flex, ...) and have them run performantly you need some form of a retained backing state anyways.
The main difference between various retained, OOP, functional, immediate, declarative, ..., approaches is how they treat this state.
For imperative/retained/OOP libraries, you operate on this state itself. Your nodes/widgets know their own state, how to render themselves, their place in the hierarchy and so on.
For immediate/functional(?) libraries, this state is a cache. It's not something you work with directly.
Despite not really liking React itself, I think it has found the best model.
You take a retained core, possibly OOP, maybe ECS or whatever, and you write a declarative wrapper around it. This lets you escape the easy-mode declarative landscape when needed, but most UI can still be simple to write.
SwiftData is just a framework that you can choose to ignore and not use at all. Even CoreData.
You can go straight to the source, and use some small layer on top of SQLite, and ignore that noise (most large apps just do that).
But, SwiftUI is being pushed as the way to do UI, and as a replacement for UIKIt/the future of apple, where it is not even near feature parity with it. That's the most troubling part of it.
I wished apple just made it as a Template Rendering framework, and integrated wit with UIKit, and just modernized UIKit a bit.
SwiftUI it is the type of framework that makes the easy things easier to accomplish but the harder things harder.
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.
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.
Apple had a real winner with ObjC and AppKit. Swift is horrendously complicated for the benefits it offers over ObjC, and SwiftUI is a massive step backwards from AppKit.
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
This is the main "problem" with autolayout. It's an amazing experience that "just works" if you think in the way that autolayout asks you to (relativity, declarative, the idea that each dimension is fully defined by exactly two constraints, isolation of dimensions aside from aspect ratio, etc).
If you don't think that way, or you're debugging somebody else's layout, then yeah, it's a nightmare. But it's shockingly easy to just redo the whole layout in that case.
I've noticed that developers who started with UIKit really have a hard time working with SwiftUI. I think this is because it's not just new syntax, it's an entirely different way to think: state is the source of truth, views are ephemeral, and you describe UI instead of managing it.
This seems to be a popular ‘controversial’ topic. I’ve been using SwiftUI for production applications and games since 2021. I drop down UIKit, Metal, or core animation when needed. But that’s no different than when I was making games in UIKit and would drop down to core animation or glyph renderers written in C etc.
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.
I was just thinking more or less along these lines - I haven't been in mobile apps for a few years now, but back then my impression was -
SwiftUI is great for "surface level" UI, that has some basic data bindings - think a basic CRUD app, which needs some navigation, and the ability to scale across the smallest iPhone to the largest macOS screen, from touch gestures to mouse input.
If you ask anything more of it, then you need to start branching off into specific libraries / tools / frameworks (UIKit, CoreAnimation etc) - which is much easier now too, but you'll always have a bad time if you try to mix the two in a single "view" / "frame".
It's a popular controversy here much the way React is a popular controversy here: people dabble in the new idiom but don't solidly master its basics; chaos ensues and consequently resentment.
Strong disagree on that. @environment is an amateurish hack, basically sugar-coating global variables as a solution to SwiftUI's poor design.
I had a strong background in UIKit; then for a product I'm building for myself, I decided to go all-in on SwiftUI. This was after it had been around for four years or more.
SwiftUI turned development, which I used to enjoy and feel good about, into a tedious trudge. I read everything I could, did the Stanford class, adopted "best practices," and really made an effort to do it right. It blows.
Unless your app is a trivial master/detail data-viewing app (as pretty much every SwiftUI example is), you wind up thrashing and performing all kinds of state-tweaking gymnastics to herd your application along through whatever tasks the user is supposed to be doing. Heaven forbid you need to walk the user through a series of steps to do or create something.
It's going to be a testing nightmare, and it suffers from every bit as much opportunity for data to get out of sync between the model and the UI as "traditional" app structure. Apple touts the "single source of truth" as gospel in SwiftUI, but you can't have that.
First of all, Swift's official position is that you should "prefer structs" over classes. But (and this is one of Swift's hokier characteristics) structs are passed by value (copied) instead of by reference. So your "single source of truth" is broken after the first function call; your data are copied all over the place.
But there's another problem with the single-source mantra: You can't just expose your core model to the UI for direct manipulation, so you have an intermediary (the so-called "viewmodel"). But that intermediary must have temporary data structures to shadow those in the core model, so the UI isn't messing directly with the model, and the user can cancel or fail when changing things without messing up the integrity of the model.
So now, once again, you don't have a "single source of truth."
The problem isn't understanding the paradigm; it's making it do useful work. Some people love to mock OO for its early and obviously cumbersome and pointless idioms, which were quickly abandoned by experienced programmers. What remains of OO is still quite useful.
I predict the same for... whatever the this mess is called. You waste so much time trying to follow the gospel of "MVVM" for no actual benefit. As I went through it, re-reading and re-digesting various pundits' viewpoints... I realized that I just had to start from scratch and build something that pays off instead of a bunch of useless ceremony.
I switched everything to classes, built managers (controllers) for the big categories of data and tasks I need to organize, and inject whatever objects I need into each view.
As for the rest of SwiftUI, its state is disgraceful. It excels at scaling UI for different screen resolutions; something that Apple neglected for waayyyyy toooo long. But there was no excuse for Apple to release a UI framework that basically didn't support the most fundamental UI paradigm of phone applications: a stack of progressive views that are programmatically manageable.
How many half-assed attempts has Apple trotted out, to do what UIKit does with ease? The latest is NavigationStack, which is still pathetic. The only way to navigate more than a level deep is to create an array of one datatype to serve as NavigationStack's "path." But this is designed to be an array of a single datatype. Look at the examples for this thing: They're applications that present a stack of views that each show... an INTEGER. In decades, I have never written an application that needed to stack up a pile of views that all show the same datatype.
And yes, I know the workaround for this where you create your own struct datatype and then fill it with enums, one for each view. But come on; t...
> The latest is NavigationStack, which is still pathetic. The only way to navigate more than a level deep is to create an array of one datatype to serve as NavigationStack's "path." But this is designed to be an array of a single datatype. Look at the examples for this thing: They're applications that present a stack of views that each show... an INTEGER. In decades, I have never written an application that needed to stack up a pile of views that all show the same datatype.
You should probably read more of the documentation than looking at examples, "to create an array of one datatype" its far from the truth. NavigationPath can be use to route to more than one type https://developer.apple.com/documentation/swiftui/navigation...
Thanks, but I did read all the doc on this several times. Looking at it again, it reminds me of the fundamental problem conveyed that page: It assumes that you're using a different datatype for every view, and can thus set up NavigationDestinations for them.
But what if you're walking the user through several steps of acting upon the same datatype? Building some kind of message, for example. First add a recipient to the message. Then create and add some content to the message. Then choose delivery options for it. In each case I'm handing the Message object to the view.
Every avenue for using this thing seemed to be crippled by some blundering assumption. Until someone came up with making a special enum for every page, which is just another piece of hokey gymnastics and extra work to "trick" the UI into doing what you want.
SwiftUI was doomed from the beginning. Not only Apple completely blew the implementation, it was actually DoA by a bunch of super bad decisions that ultimately make it incredibly hard to work with and manage, especially on bigger apps.
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.
Maybe unrelated, but as an Android dev, a few years ago I wanted to look into SwiftUI.
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.
Despite all the trends, I still really like HTML for structure, CSS for styling, and JavaScript for logic.
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.
> I have to think about everything, everywhere, all the time.
I think this is familiarity speaking, which is what you're expressing earlier in the comment anyway. The reality is that we have to think of everything when telling a machine what to do. Exactly how we get that done is preference.
As a solo app developper for two years mainly for apple platform(previously do networking infra software using C/Go)
After two many trial and fail, now it's quite clear to me that for simple UI I will use swiftUI(such as help sheet or simple toggles), for complex and performance first, I will just use UIKit instead, it save a log of time and actually the imperative UIKit is also quite easy to read and review
the feasibility of review is important because code is not mainly written by agent, though as my understanding of UIKit grows I can smell the bad part and let it rewrite
SwiftUI has a lot of failings, but it can also do a lot of things that are really tricky in UIKit.
I can render Metal shaders trivially in SwiftUI. Rendering glows, and blurs, and animated effects is much easier in SwiftUI than in UIKit, just use `.blur(radius:)` or `.blendMode(...)`
I have used AppKit and then UIKit since its inception. Creating visual effects like layer masks that modulate the opacity of underlying views is trivially easy in SwiftUI — far easier than the boilerplate and constant bookkeeping that CALayer's mask requires.
So a lot of the advanced full-screen animations in some of my games and apps are SwiftUI, because they are performant, provide the cool effects and animations, and work great. A lot of the simple get-the-job-done views and tool palettes in my apps are also SwiftUI, again because they don't ask much and get the job done, and look great.
However, where SwiftUI falls down is exactly what was demoed in the video: large collections of thumbnails that fetch asynchronously? Use UIKit. Multi-thousands of items in large, complicated lists? You can try SwiftUI, but you'll need to learn how to optimize it.
Other things, not mentioned in the video, that are more annoying in SwiftUI: want to take control of a transition between views, end-to-end? Not really possible in SwiftUI. There are bugs with ZoomNavigationTransition that affect all of Apple's own apps, and you aren't gonna be able to fix them without switching to UIKit.
You know those games you buy as Early Access while they're still in development, with the implied promise that development will be done some day? And how many of those games have stayed Early Access over so many years that you stopped believing they will ever be done? That's SwiftUI. I won't touch it.
74 comments
[ 2.9 ms ] story [ 67.9 ms ] threadApple'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.
This isn't 7 years of development, but 7 - 12 years after release. And to most these past 7 - 12 years are an ongoing beta development. It is unfinished, unpolished with no end in sight. And I have been extremely critical since the beginning.
But the problem runs much much deeper. It isn't the technology that is the problem, not the devs who are making it. It is the person making the decision as to WHY this was allowed from the get go. WHY this was allowed to be released, or even before all that WHY resources for development of these ideas were allowed in the first place.
For every yes that are a thousand no. Instead a lot of Apple's software development can be summarised as resume or KPI bonus driven development. It is not as bad as Google and Microsoft, but it is clear Apple have this problem a well.
If you look back into Jobs era of Apple software, ( and not just software ) Apple manage to have done most things 2x better with half the resources. The whole Apple now is bloated. And yet everyone is chanting Craig Federighi all the way.
And it is funny because for the vast majority of these 7-12 years I was the only few on HN and Twitter that was extremely skeptical of it, to the point I gave up writing ( or ranting ) about it before majority Swift and Swift UI developers negative sentiment emerged.
And I have often asked the same question every single time, what if they just spend one fifth of the resources to iterate and improve C / Objective-C and Cocoa. All the resources on Swift and everything adjacent to it could have been better spent somewhere else.
I have high hope for John Ternus, hopefully he gets his political game right and manage to change course for Apple software somewhere down the line.
And Swift is simply just not that language. Apple should have just invented a specialized UI DSL to support SwiftUI. And continued to support good old MVC first-class. Explicit Constraints, Lifecycle Clarity and Programmable Control make UIKit apps easier to debug and fix.
SwiftUI should cleanly extracted out its reactive framework as a standalone, public framework for non-UI or decoupled use-cases. That would have helped in fixing a lot of issues.
I don't think we have to wait 10 years, we can say it today.
You can't have Cocoa without Obj-C, or at least a langauge and runtime with that philosophy.
Apple software has been on a clear decline for a seriously long time, and it's propped up almost entirely by them pulling off Apple Silicon combined with how Microsoft have somehow been even worse.
Swift should have just been a much improved syntax over that same runtime. It would have avoided so many headaches. For one they wouldn't have made the awful decision to have return-type overloading and completely ruin the typechecker's performance in the process.
SwiftUI should have unapologetically been a convenient, reactive wrapper over UIKit and AppKit, rather than treating them as deprecated implementation details that devs nonetheless keep having to drop down into.
These decisions come down to ego, of wanting to do away with the old and carve out your own legacy separate from it. Nice if you want a promotion but not so nice if you're trying to make a long lasting ecosystem for developers to build upon.
At least Swift and SwiftUI have a reasonable interoperability story with the past. Can't say the same about Microsoft's graveyard of UI frameworks.
if they had really just done objective-c without the c like, the original moniker said...
Because it was good.
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.
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.
> Data flow in SwiftUI is indeed reactive—but sometimes I wish it wasn’t, because it’s reactive in all the wrong ways. It often reacts to changes it should ignore, and it ignores the changes you actually care about. To me, SwiftUI’s reactivity is a black box: It makes achieving predictable behavior almost impossible.
In Compose, seeing rememberXXX(key1, key2) sprinkled all over with keys makes following the code difficult.
Then add some side effects like LifecycleEventEffect(Lifecycle.Event.ON_RESUME) { ... read permissions and render warning if we can't do something ... } and it becomes even more difficult to comprehend. Much of the Android framework APIs are not reactive, and polling on these UI events is still necessary (permission could have changed if the user put the app in the background, and you can't listen to them via Flow etc).
As the author says, these frameworks make the static data dependencies explicit but often at the expense of what is changing and why.
When I see rememberXXX(key1, key2) { } the first thing that comes to mind is, why would key1 and key2 change, and often that is not obvious.
The main difference between various retained, OOP, functional, immediate, declarative, ..., approaches is how they treat this state.
For imperative/retained/OOP libraries, you operate on this state itself. Your nodes/widgets know their own state, how to render themselves, their place in the hierarchy and so on.
For immediate/functional(?) libraries, this state is a cache. It's not something you work with directly.
Despite not really liking React itself, I think it has found the best model.
You take a retained core, possibly OOP, maybe ECS or whatever, and you write a declarative wrapper around it. This lets you escape the easy-mode declarative landscape when needed, but most UI can still be simple to write.
But, SwiftUI is being pushed as the way to do UI, and as a replacement for UIKIt/the future of apple, where it is not even near feature parity with it. That's the most troubling part of it.
I wished apple just made it as a Template Rendering framework, and integrated wit with UIKit, and just modernized UIKit a bit.
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.
IMO it goes further than that: It makes easy things easier and hard things impossible.
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.
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
If you don't think that way, or you're debugging somebody else's layout, then yeah, it's a nightmare. But it's shockingly easy to just redo the whole layout in that case.
SwiftUI is not Swift. It is implemented using complex Swift features, but it is a huge step backwards in dev-ex from autolayout and UIKit.
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.
SwiftUI is great for "surface level" UI, that has some basic data bindings - think a basic CRUD app, which needs some navigation, and the ability to scale across the smallest iPhone to the largest macOS screen, from touch gestures to mouse input.
If you ask anything more of it, then you need to start branching off into specific libraries / tools / frameworks (UIKit, CoreAnimation etc) - which is much easier now too, but you'll always have a bad time if you try to mix the two in a single "view" / "frame".
I'm not surprised that's still true today.
Strong disagree on that. @environment is an amateurish hack, basically sugar-coating global variables as a solution to SwiftUI's poor design.
I had a strong background in UIKit; then for a product I'm building for myself, I decided to go all-in on SwiftUI. This was after it had been around for four years or more.
SwiftUI turned development, which I used to enjoy and feel good about, into a tedious trudge. I read everything I could, did the Stanford class, adopted "best practices," and really made an effort to do it right. It blows.
Unless your app is a trivial master/detail data-viewing app (as pretty much every SwiftUI example is), you wind up thrashing and performing all kinds of state-tweaking gymnastics to herd your application along through whatever tasks the user is supposed to be doing. Heaven forbid you need to walk the user through a series of steps to do or create something.
It's going to be a testing nightmare, and it suffers from every bit as much opportunity for data to get out of sync between the model and the UI as "traditional" app structure. Apple touts the "single source of truth" as gospel in SwiftUI, but you can't have that. First of all, Swift's official position is that you should "prefer structs" over classes. But (and this is one of Swift's hokier characteristics) structs are passed by value (copied) instead of by reference. So your "single source of truth" is broken after the first function call; your data are copied all over the place.
But there's another problem with the single-source mantra: You can't just expose your core model to the UI for direct manipulation, so you have an intermediary (the so-called "viewmodel"). But that intermediary must have temporary data structures to shadow those in the core model, so the UI isn't messing directly with the model, and the user can cancel or fail when changing things without messing up the integrity of the model.
So now, once again, you don't have a "single source of truth."
The problem isn't understanding the paradigm; it's making it do useful work. Some people love to mock OO for its early and obviously cumbersome and pointless idioms, which were quickly abandoned by experienced programmers. What remains of OO is still quite useful. I predict the same for... whatever the this mess is called. You waste so much time trying to follow the gospel of "MVVM" for no actual benefit. As I went through it, re-reading and re-digesting various pundits' viewpoints... I realized that I just had to start from scratch and build something that pays off instead of a bunch of useless ceremony.
I switched everything to classes, built managers (controllers) for the big categories of data and tasks I need to organize, and inject whatever objects I need into each view.
As for the rest of SwiftUI, its state is disgraceful. It excels at scaling UI for different screen resolutions; something that Apple neglected for waayyyyy toooo long. But there was no excuse for Apple to release a UI framework that basically didn't support the most fundamental UI paradigm of phone applications: a stack of progressive views that are programmatically manageable.
How many half-assed attempts has Apple trotted out, to do what UIKit does with ease? The latest is NavigationStack, which is still pathetic. The only way to navigate more than a level deep is to create an array of one datatype to serve as NavigationStack's "path." But this is designed to be an array of a single datatype. Look at the examples for this thing: They're applications that present a stack of views that each show... an INTEGER. In decades, I have never written an application that needed to stack up a pile of views that all show the same datatype.
And yes, I know the workaround for this where you create your own struct datatype and then fill it with enums, one for each view. But come on; t...
You should probably read more of the documentation than looking at examples, "to create an array of one datatype" its far from the truth. NavigationPath can be use to route to more than one type https://developer.apple.com/documentation/swiftui/navigation...
But what if you're walking the user through several steps of acting upon the same datatype? Building some kind of message, for example. First add a recipient to the message. Then create and add some content to the message. Then choose delivery options for it. In each case I'm handing the Message object to the view.
Every avenue for using this thing seemed to be crippled by some blundering assumption. Until someone came up with making a special enum for every page, which is just another piece of hokey gymnastics and extra work to "trick" the UI into doing what you want.
SwiftUI is a laudable attempt to idiot-proof UI, but it sacrifices too much and ultimately fails.
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.
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.
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.
I guess I'm even older, because I prefer HTML4, without CSS. And I like using tables for layout instead of divs.
I always hated CSS.
I think this is familiarity speaking, which is what you're expressing earlier in the comment anyway. The reality is that we have to think of everything when telling a machine what to do. Exactly how we get that done is preference.
After two many trial and fail, now it's quite clear to me that for simple UI I will use swiftUI(such as help sheet or simple toggles), for complex and performance first, I will just use UIKit instead, it save a log of time and actually the imperative UIKit is also quite easy to read and review
the feasibility of review is important because code is not mainly written by agent, though as my understanding of UIKit grows I can smell the bad part and let it rewrite
I can render Metal shaders trivially in SwiftUI. Rendering glows, and blurs, and animated effects is much easier in SwiftUI than in UIKit, just use `.blur(radius:)` or `.blendMode(...)`
I have used AppKit and then UIKit since its inception. Creating visual effects like layer masks that modulate the opacity of underlying views is trivially easy in SwiftUI — far easier than the boilerplate and constant bookkeeping that CALayer's mask requires.
So a lot of the advanced full-screen animations in some of my games and apps are SwiftUI, because they are performant, provide the cool effects and animations, and work great. A lot of the simple get-the-job-done views and tool palettes in my apps are also SwiftUI, again because they don't ask much and get the job done, and look great.
However, where SwiftUI falls down is exactly what was demoed in the video: large collections of thumbnails that fetch asynchronously? Use UIKit. Multi-thousands of items in large, complicated lists? You can try SwiftUI, but you'll need to learn how to optimize it.
Other things, not mentioned in the video, that are more annoying in SwiftUI: want to take control of a transition between views, end-to-end? Not really possible in SwiftUI. There are bugs with ZoomNavigationTransition that affect all of Apple's own apps, and you aren't gonna be able to fix them without switching to UIKit.