SwiftUI is convenient, but slow (2022)
notes.alinpanaitiu.com
notes.alinpanaitiu.com
https://news.ycombinator.com/item?id=33772876 (189 comments)
Many smart devs tried to help me, and I added some of their recommendations:
- caching views to a bitmap using Metal
- trying smaller windows so that less pixels have to be redrawn
Unfortunately nothing made a noticeable difference, this will have to wait until I get a really boring weekend.It's doc description seems to be closer to what you need than the `id()` modifier.
<https://developer.apple.com/documentation/swiftui/view/equat...>
> Prevents the view from updating its child view when its new value is the same as its old value.
Also, https://swiftwithmajid.com/2020/01/22/optimizing-views-in-sw...
Some things still re-render the world and are VERY slow though (ifs/switch inside ForEach with many rows easily brings app to hard lagging, even if doing everything to prevent it -> makes SwiftUI useless for generic row usecases).
Seems like the app doesn’t have a huge amount of UI and could be converted in a few months.
Would help understand the context on posts that describe tech that has evolved rapidly and probably still will
UIKit and AppKit aren't slow though, and Apple has every incentive to make this faster (they wrote SwiftUI's dependency graph in C++ after all, so they do seem to care), which makes me think there is just inherent slowness from the dependency analysis that is required for these sorts of systems (that seems to be what I see on the profiles).
[1] https://audulus.com [2] https://sculptura.app [3] https://github.com/audiokit/flow
iOS has felt so stupidly slow since then, because you're waiting for all of these dumb screens to swipe and pan and you can sit there and tap a button in the middle of all of this like 3-5 or more times and the damn phone does nothing until everything is all settled and complete, and only then will it listen to your tap event.
Who are these utter grandpas who make these stupid UI decisions?
Is this specific to certain types of scroll views? I just played around in my Mail app inbox (most likely built with UICollectionView) initiating flick-scrolls and then double-tapping to stop the scroll and select the message under the tap and it works exactly like the original behavior you describe with zero delay.
I consider it basically impossible to take more than 1ms on the CPU to update+render an UI screen, even the most complex one.
As long as rendering is done on the GPU it should not be more than 2ms even on full-screen 4K.
The architecture of SwiftUI must be really weird to be slow/janky on a M1.
An active style where where when state is updated side effects happen directly inside the same call graph.
And this passive disconnected spooky action at a distance where you update state and something else is supposed to/might execute side effects at some unspecified time in the future.
The first way there is no magic going on. The second way it's all magic. I try to avoid writing code the second way if at all possible.
Even with ImGui, you have to draw a lot to drop below 120fps on an M1 Mac.
A retained mode GUI could technically be much faster, even if I have yet to see one in the wild.
My only complaint is it's being developed so slow! Which isn't a fair complaint, really, I just want it!
SwiftUI apps stick out like a sore thumb, just as bad as Electron if not worse. The worst offenders on my phone are SwiftUI. And it is horrible on Mac - see System Settings, which has somehow managed to turn their lead over Windows into being worse than the Windows 10 era settings app.
SwiftUI apps are. not. native. Full stop.
Apple needs to try harder if they want to maintain their reputation for high-quality, high-polish, premium software experiences.
It likely started as an answer to React for iOS and then late became a cross-platform toolkit. The API to get what you want and expect is terribly documented and poorly named. Countless times I stumble across the "right way" to do something, and it works well.
You just won't find it on StackOverflow (or ChatGPT) nor in any tutorial site. It will be buried in a small section of sample code from Apple or listed on a slide in a WWDC video.
My biggest complaint is that it tries to be too magical. Sometimes certain values are ignored and no amount of working around it will force it. Some internal decision for optimization didn't consider a specific use-case and there's no way to know. All I get is, configured one way, everything works, but change it, and suddenly it's ignored.
It took UIKit a decade to ease up on magical behavior, but SwiftUI didn't seem to learn that lesson and so it's back to square one.
The constant animations are what makes me dread and despise working with Apple software. Each time something moves for no good reason whatsoever, I die inside a little. Every few seconds.
> [...] the same animation was driving me nuts because I was switching spaces so often, that the animation was slowing me down
Exactly. Props to the author for making them possible to turn off. The operating system at large still has _tons_ of them that you can't get rid of, but it's the thought that counts.
> Reacting to keyboard events is still something I do outside of SwiftUI
SwiftUI is a nice idea in principle, what with being reactive, but I found that I cannot achieve anything worthwhile without piercing down into the lower layer of AppKit. And then I asked myself why do this clownery in the first place.
Ultimately, trying to learn Apple frameworks has made me love GTK+, because it's so beautiful and elegant in comparison (disregarding that it's currently deeply broken on macOS).
I want to like reactive, but between its inherent properties, how SwiftUI does it, and the fact I'm having to use VIPER as the architecture for the project…
…I don't like it, but I also don't know exactly where the issue is. And "not knowing where the real problem is" means I also can't add any productive suggestions for how to improve matters, to the very obvious annoyance of the iOS lead.
This is your problem. VIPER is just a huge amount of worthless bureaucratic toil. It’s only useful if your only option to scale development is putting as many warm bodies in seats as possible and need to enforce mediocrity to keep things from going off the rails. It’s not great in general and particularly bad for SwiftUI.
Switching spaces on macOS is one of the best examples of easy improvements. There's info being communicated (where the user is being swept away to, where the destination desktop sits in relation to the current one) but it should probably be sped up by at least 40% and not block user interaction so if there's a focused textfield at the destination desktop, the user can start typing mid-transition and no text will be lost.
On phones I usually speed animations up rather than turning them off entirely. But on the Pixel Watch the animations are so gratuitous and add so much friction to my use of the watch that I turn them off entirely.
Have you tried System Settings > Accessibility > Display > Reduce motion?
defaults write com.apple.dock autohide-time-modifier -float 0.1
defaults write -g NSUseAnimatedFocusRing -bool NO
defaults write com.apple.dock springboard-show-duration -float 0
defaults write com.apple.dock springboard-hide-duration -float 0
defaults write com.apple.dock springboard-page-duration -float 0.1It's hard to just give you a generic answer. I can only really compare to Win32, Cocoa, and some parts of the web stack.
Came here to post ~the same thing.
Mine was going to be a lot more aggressive in favor of Flutter, ex. SwiftUI doesn't have hot reload, looks like it _always_ needs to repaint on a state change (whereas Flutter has that widget | paint boundary that keeps things brutally efficient). Once you use InheritedWidgets / Provider / Riverpod you get provably minimal CPU usage, i.e. minimal rebuilds, the subwidgets never repaint unless you want them to. Top it off with pervasive StatelessWidgets and you have provably minimal RAM usage.
I guess what I'd say is, it doesn't add much to the conversation: every view framework that needs to repaint a deep view tree entirely has issues, and in retrospect, there's deeper observations to make w/r/t SwiftUI and flutter.
However, things are looking up with the change from Skia to Impeller and I'm hopeful about the future.
Flutter in 2020 could render a complicated UI (new Google Assistant UI with glowing effect) on a 2015 $200 Android, and there was simply no way to do the same in Android proper. (Source: built Android version at Google and built Flutter version after for no particular reason, side project to teach myself Flutter)
People tend to remember Flutter anecdotes that correlate well with previous xplatform framework fundamental issues, but in Flutter's case, they're not fundamental, they're more "holding it wrong" / "could use better docs"
That being said it's probably a year or two away from me being brave enough to post that on an HN article (safe here, because articles old, weekend, and not directly related to Flutter).
Rive renderer is very impressive too. https://twitter.com/gordonphayes/status/1654107954268782595