The gold standard fluid interactions on iOS are built using in-process client animations (like SwiftUI does it) and not render-server animations (like CoreAnimation does it). This is common knowledge inside of Apple’s UI framework and system experience teams.
A close inspection of iOS’s evolution reveals the gradual upgrading of system experiences written using render-server animations (that often disable user interaction) with ones using client animations (that are interruptible and interactive). The app switcher for iPhone X, the Dynamic Island, and Liquid Glass bars are prime examples of this trend.
The other thing that makes these experiences feel so fluid is their use of spring animations that preserve velocity, rather than Bézier curve easing functions. To get velocity preservation, you need to be able to interrupt a spring animation and retarget it or drive it with a gesture. That’s a lot easier to do when the animation is running in the same process as the event handling.
When we were first pitching SwiftUI, two of our go-to demos were a recreation of the iOS 9 navigation and Home Screen interactions which were fully interactive and interruptible, at a time when the actual implementations of those experiences in the OS disabled user interaction and ran server-side animations.
CoreAnimation is great and the framework does much more than animation. You can build a fine app using its server-side animations. But if your UI framework can’t do efficient main thread client animations, there’s a ceiling to the quality of the experience your app can provide.
Fun fact: the creator of CoreAnimation is one of the creators of SwiftUI!
The decision to run animations in the app process rather than the render server (as CoreAnimation does) was one of the earliest and most fundamental decisions we made when designing SwiftUI.
Some of the most distinctive experiences of using an iPhone, like UIScrollView rubber banding and SpringBoard app switching are only possible as client-side animations.
But these experiences aren’t easy to build with UIKit!
This is because if you want a UI to be fully interactive and interruptible by the user while it’s animating, it has to be running in the same process as the event handling.
In fact, in iOS 18 we added new APIs to AppKit and UIKit to adopt the SwiftUI client-side animation model.
There are a lot of valid critiques of SwiftUI. The fact that SwiftUI doesn’t use CoreAnimation for its animations is not one of them.