A looping animation looks free. On macOS, two of mine were not. Both shipped in my own apps, and both were measured on release builds, not Debug.
1. A glow that kept running after its popover closed
Soluna is my menu bar calendar. Today’s cell had a slow “breathing” glow, a .repeatForever animation on one flag. My own Mac health app, What Happened, reported Soluna using about 134 core-minutes a day in the background.
The cause: AppKit keeps an NSPopover’s hosting view alive between opens. So after the popover closed, SwiftUI went on re-rendering its whole view tree every frame. sample showed the main thread in NSHostingView.layout and ViewGraphRootValueUpdater.render with nothing on screen.
I proved it by toggling. Open and close the popover: 17 to 19% of a core, and it stays. Close it on a month that does not contain today’s cell: 0.0%. Back to today: 17% again.
The rule I took from it: any looping animation inside a popover or panel has to stop when it closes.
2. A TimelineView in every list row
Wick is my deadline tracker, and a deadline can show a small flame. Each flame was a TimelineView(.animation) drawing into a Canvas. With the window in front and idle, the app sat at 32% of a core. With flame motion off: 0%. A single flame: about 12%.
I tried the obvious fixes first. Moving the per-frame math out of the Canvas, splitting a still layer from a live one, and shrinking the live Canvas to a 92 pt box did not help. The drawing was never the cost. Every TimelineView(.animation) tick made SwiftUI update and lay out the whole window.
What worked was handing the loop to Core Animation: an NSViewRepresentable holding CAShapeLayers, with the path animated by a CAKeyframeAnimation over 24 precomputed frames. The app went from 32% to 0.3%.
How to check your own app
Open the view, close it, then watch the process for a minute. ps -o time= -p <pid> should barely move. If it climbs, run sample <pid> and look for NSHostingView.layout on the main thread.
One-shot SwiftUI transitions are fine. It is the loops that need a second look.
I make Soluna, Wick and What Happened on my own as AppsByMo. If you want a short email when I ship a Mac app or a big update, twice a month at most: https://appsbymo.app/?ref=devto#signup-h
Top comments (0)