Hi Lukas,
thanks a lot for making this gist accessible!
Unfortunately I can’t help concerning NSScrollView: we rolled our own scrolling quite a while ago for other reasons. Seems to be of benefit once again.
Post
Replies
Boosts
Views
Activity
Hi Mark,
great summary!
One little thing, though: overwrites of -viewWillDraw should probably forward to super. If I recall correctly, this was crucial on older OS versions to dispatch the message to sub views, although that has been changed at some point.
Best regards
Kai
Hi Mark, sorry, I should have mentioned that we set .layer.contentFormat each time in -viewWillDraw (and in -layerWillDraw under iOS). When investigating this back when iOS 12 was new we found that the format is often reset by the OS. I didn’t investigate this further under macOS, just copied the fix from iOS.
One difference under macOS is that .layer.contentFormat returns kCAContentsFormatRGBA8Uint, even before setting it. Nevertheless setting this same value does make a difference. Under iOS, it returns "automatic" before changing it.
Kai
We found a fix for this issue which we derived about two years ago when the same problem turned up under iOS 12: set view.layer.contentsFormat = kCAContentsFormatRGBA8Uint.
Reasons seems to be the automatic backing store format adaption introduced in iOS 12 (and now as it seems under macOS 11). With this enabled (the default, .contentsFormat == "Automatic" (no constant for this in the headers)), views always pass the full bounds rectangle to -drawRect:, although sometimes somehow clipping the redraw to the actual invalidated area (not using the Quartz clip, which also matches the full bounds).
We are seeing the same issue. We invested quite a lot in minimizing drawing to optimize performance, which is in vain under this bug.
Additionally, even under Catalina, -getRectsBeingDrawn:count: seems to return just one rectangle (which matches the direct rectangle passed to -drawRect:), no matter what was invalidated before. For example, after sending -setNeedsDisplayInRect: to the same view twice with two small non-overlapping rectangles, -getRectsBeingDrawn:count: returns a single rectangle which is the union of the two rectangles passed to -setNeedsDisplayInRect:. Actually drawing with different colors reveals that the clip is still set to just the two small rectangles, but the OS no longer reveals this information.