I think Apple really screwed up th dedign of SwiftUI. We're currently refactoring our apps back to AppKit/UIKit. The first 90% is easy, the final 10% is often impossible. You shouldn't have to do what the article author did and change your UI designs due to bugs in the UI framework.
For anyone that's enjoying the idea of SwiftUI (but not the reality), Jetpack Compose on Android might be up your alley.
It doesn't try and wrap legacy views-the framework renders every pixel itself.
This allows you to get the rapid build speed of declarative UI but also an extremely high level of polish.
As a bonus, the core components are open source, so you can see how a Button or CircularProgressIndicator works (for example)
Compose uses normal functions that render themselves and return nothing (rather than returning a crazy complex typed view like SwiftUI does-often breaking the compiler). And "remember {}" blocks for state feels so much simpler than every view being a struct with @State.
In a funny way this functions-not-objects approach is the most surprising design choice made by Compose considering the Java/Kotlin ecosystem it exists within.
You’re right, you shouldn’t have to but it seems to be a penalty you currently have to pay if you go all-in with SwiftUI at this stage in its lifecycle. Admittedly, it’s still relatively/technically immature compared to its predecessor, and so you expect certain limitations in comparison. But four versions in, some of these things I’m surprised continue to be points of frustration. I imagine if Apple themselves were stress testing/dog fooding it exclusively then these are things that would have been ironed out by now. The irony, right?
And you’re right, SwiftUI “onboarding” is almost deceitfully simple/natural. And, in general, there being no friction in its UX makes it so easy to gradually build up issues in complete ignorance. And when it does become apparent, you’re working with a gorilla, i.e. steps to rectify are expensive.
I look forward to trying out Compose for all the reasons stated. Thanks for sharing !
The one other thing I’d add as being a major source of frustration and anxiety is SwiftUI’s update cycle. It’s acceptable for there to be issues in any technology, whatever its age, but it’s not satisfactory to need to wait 12 months for the possibility — not even certainty — of a fix. This is what attracts me most about Compose: the transparency and speed of innovation.
I don’t understand. Why stubbornly insist on using pure SwiftUI when UIKit components can be trivially integrated into a SwiftUI app?
I have personally dropped using any kind of List/Scroll component because I know I can build a better version in UIKit without much thought.
I have also “converted” a former UIKit app to SwiftUI by dropping the business logic in an ObservableObject and wrapping the rest of the existing code in UIView*Representables. This whole process took maybe a day or two, it’s surprisingly easy.
Also, performance pro-tip: Use @Published in an ObservableObject sparingly with most state changes in PassthroughSubject or CurrentValueSubject.
Great question. I don’t think I have an answer that will satisfy you.
Our natural instinct was never to revert to UIKit because we have no experience working with it. This combined with the fact that our problems built up gradually over time, i.e. there were no signs of trouble. By the time we had, we didn’t think — right or wrong — that it would be straightforward to pivot. To be fair to SwiftUI (and us), we’ve made meaningful progress in our optimisation efforts but we can’t consider the effort complete yet.
The other more meta point I would add is if everyone — including Apple themselves — defaulted back to UIKit whenever they hit an obstacle, then SwiftUI stands no chance of becoming a product you can depend on unconditionally with no caveats.
Publishers are dangerously easy to employ, right? This a harsh lesson learnt. Again, when something effectively has no learning curve, then it’s too easy to take for granted. And just as it’s naive/wrong of me to expect my users to use the product in the intended way and not iterate based on the reality of everyday usage, same logic should apply to SwiftUI’s mechanics/UX.
First of all, congratulations on publishing your app! I’ve never come close to that, although having created a few PoC’s.
On my 11 Pro the animations are sluggish, buttons presses are missed when switching from plan to browse and the device gets pretty warm indicating heavy cpu usage. I’ve read that you’ve already put a lot of time in investigating performance issues, so is then expected with a more complex UI, is this the best one can do with SwiftUI, or do you need to be an even more experienced expert in SwiftUI to further improve things?
1) we’re still in beta, and so we’re aware that the experience still has room for improvement in terms of optimisation. We’ve made big strides recently, but there’s still ways to go clearly. We won’t consider ourselves out of beta until we are happy with performance across the board. First wave of improvements imminent, and we’ll continue to between now and full release.
2) that said, based on our dogfooding, profiling and user feedback, your experience seems to be substantially worse than anything we’ve encountered/been made aware of. We have stress tested the app too with a calendar filled with an unusually high number of events on a daily basis, and although I wouldn’t describe performance as _good_, it’s borderline acceptable at worst. It would be great — if you are available — to learn more about your setup (bardi@timing.is) so we can have a better understanding of what could be tripping it up so badly for you. Also, as we make progress with optimisation work, it would be super helpful to use your device as a point of reference when performing more anecdotal before/after comparisons.
3) as suggested in the post, we wouldn’t describe ourselves as SwiftUI _experts_. So, I don’t for a moment want you to takeaway that this is the best SwiftUI can do when managing an app of moderate complexity. I’m confident we’ll be able to make inroads ourselves, but most definitely everything would be running smoother already if we had direct access to expertise. But again this highlights the main point that hopefully wasn’t lost: it shouldn’t require experts to make SwiftUI perform well, and — on the flip side — it shouldn’t be so easy to make SwiftUI perform poorly.
The other being, it shouldn’t be impossible to perform certain interactions that for a four version old product you would expect it to be able to support. I understand like any tech, you need to prioritise what it can do out of the gate, pushing forward most common use cases. At this point though, I shouldn’t need to jump through unclear hoops to get a scrollTo function to work in a LazyVStack.
For anyone that's enjoying the idea of SwiftUI (but not the reality), Jetpack Compose on Android might be up your alley.
It doesn't try and wrap legacy views-the framework renders every pixel itself.
This allows you to get the rapid build speed of declarative UI but also an extremely high level of polish.
As a bonus, the core components are open source, so you can see how a Button or CircularProgressIndicator works (for example)
Compose uses normal functions that render themselves and return nothing (rather than returning a crazy complex typed view like SwiftUI does-often breaking the compiler). And "remember {}" blocks for state feels so much simpler than every view being a struct with @State.
In a funny way this functions-not-objects approach is the most surprising design choice made by Compose considering the Java/Kotlin ecosystem it exists within.