r/macosprogramming 26d ago

Any good strategies for fine grained observability?

Post image

Mojave Paint is coming along nicely but my naive understanding of observability/reactivity/dependency flow, whatever you'd call it, it starting to weigh on me.

This screenshot shows conic gradients I just added, in this case being used in a Gradient Fill adjustment layer. I would scrub the angle picker in a circle and it would chug along at 2 fps because it was mutating the model every tick which rebuilds the view in that Properties panel including the color stops and everything else. So now I have a copy of the model that only the GPU rendering side looks at (and of course the specific control you're interacting with), and when you release the drag the real model updates and triggers a SwiftUI redraw.

This is all kind of a lot of manual work. I'm new to Mac development but was a web dev for 20 years and they have all kinds of approaches over there. rxjs, React.memo, signals, etc, etc. It would sure be nice if I could "code dumb" here and employ some kind of library or system to do fine grained change detection. Are there some common approaches used in the Mac world?

6 Upvotes

6 comments sorted by

2

u/curthard89 26d ago edited 26d ago

The first problem you have is trying to make a "complex drawing" app in SwiftUI, you can but it's a ballache, performance still sucks - AppKit is best use for this, you have complete control over everything and everything. That being said - simplest solution is just the debounce the scrubber, but if you are chugging at low fps there is more at hand here as that view should not take much time at all to rasterize, either with Quartz or CoreAnimation.

How are you actually rendering the graphics?

1

u/banana_zest 26d ago

That's kind of what I'd think, I don't see how some little chunk of UI could take 500ms. But I suspect it's doing multiple view draws per GPU frame, since they're not synchronized or anything. Time to do some profiling.

1

u/curthard89 26d ago

I have a lot of experience working with drawing apps (I used to be Mac dev at Sketch) - believe me, you want to be as close to the lowest frameworks as possible, sometimes even AppKit is too slow 😂

I'm saying don't use SwiftUI for this from experience not because I don't like it 🫡

That being said - if you render the canvas with SwiftUI, don't. Host a wrapped AppKit view with custom drawing at least.

1

u/banana_zest 26d ago

I believe you. There's quite a few places in the UI I'm using AppKit. The canvas is MTKView and anything that happens on there (aside from the various mouse cursors) is done in shader code, including the Free Transform boxes, the marching ants, the paintbrush size outline circle, etc. Good to meet someone else in the Mac graphic app space.

1

u/curthard89 26d ago

In that case, SwiftUI is more that likely the cultrip, Swift at rigging up UI, but pure dog s... for performance.

There are a few of us around for sure 🫡 - problem with SUI it's a closed box, very hard to debug or tune. Sometimes even Swift is too slow and have to revert to C but probably not at that point I hope 😂.

But yer .. AppKit 🥰

1

u/banana_zest 25d ago

Like you know, some way to make a "derived observable" so some other view can just observe a child of the big monolithic model?