-[NSView (un)lockFocus] deprecated, what to use instead?

I hit major road blocks in migrating one of my Objective-C Cocoa applications away from -[NSView (un)lockFocus] and -[NSBitmapImageRep initWithFocusedViewRect:].

In a transcript of a presentation on WWDC2018 I read:

With our changes to layer backing, there's a few patterns I want to call out that aren't going to work in macOS 10.14 anymore. If you're using NSView lockFocus and unlockFocus, or trying to access the window's graphics contents directly, there's a better way of doing that. You should just subclass NSView and implement draw rect. ...

Of course, we all implemented -[NSView drawRect:] for decades now. The big question is, how can we do incremental (additional, event driven) drawing in our views, without redrawing the whole view hierarchy. This is the use case of -(un)lockFocus, and especially when drawing of the base view is computational expensive. Wo would have thought that people use -(un)lockFocus for regular drawing of the NSView hierarchy.

I tried to get away with CALayer, only to find out after two days experimenting with it, that a sublayer can only be drawn if the (expensive) main layer has been drawn before —> dead end road.

After all, I implemented a context dependent -[NSView drawRect:]. Based on a respective instance variable, either of the (expensive) base presentation of the view or the simple additions are drawn. Is it that what Apple meant «… just subclass NSView and implement draw rect?»

From the point of view of object oriented programming, using switch() in methods to change the behaviour of the object is ugly - to say the least. In the moment I don't see a better option, since ugly or not, in any case, I don’t want to redraw the whole view hierarchy only for moving a crosshairs in a diagram.

This application CVA draws into a custom diagram NSView electrochemical and other scientific measurement curves which may consist of a few thousands up to millions of data points. The diagram view provides a facility for moving crosshairs and other pointing aids over the displayed curves, by dragging/rolling with the mouse or the touch pad, or by moving it point by point with the cursor keys.

Diagram generation is computational expensive and it must not occur only because the crosshairs should be moved to the next data point.

So for navigating the crosshairs (and other pointing aids), a respective method locks the focus of said view, restores the background from a cache, caches the background below the new position of the crosshairs using -[NSBitmapImageRep initWithFocusedViewRect:], draws the crosshairs and finally unlocks the focus.

All this did not work anymore since 10.14, until I implemented the workaround utilizing the context sensitive -[CVADiagramView drawRect:].

Copyright © Dr. Rolf Jansen - 2022-03-13 00:11:32