According to the documentation for NSView's drawRect:
If your app manages content using its layer object instead, use the updateLayer method to update your layer instead of overriding this method.
I have an NSView
with subviews that are provided by the framework, and they all draw using drawRect:
. This framework-provided view is a subview of an NSView
for which I require a layer. Because my framework-provided view is a descendant of a layer-backed view, drawRect:
isn't usually called, especially in cases where the window is made active or inactive (the view needs to update to reflect its (in)active state).
Of course if I make my containing view not layer backed, updates occur when the window is made active or inactive.
Without modifying the framework into a custom fork, what's the best avenue for making sure drawRect:
occurs when needed in my framework-provided view?
Thanks.
Edit 25-Aug-2018:
It looks like the trick is to set one of the views in the hierarchy to, e.g., [view setCanDrawSubviewsIntoLayer:YES
, which according to the documentation uses all of the subviews’ drawRect:
to add their drawing to its own layer. However this seems to work only through 10.13, and is broken in the 10.14 beta. I'll continue to look for a potential API change, unless this is a 10.14 beta bug.
Since the issue is still unresolved, it's not really answered yet.
-drawRect:
method of a superview is not responsible for calling/triggering/invoking the-drawRect:
of its subviews. Each view (layer or not) gets drawn when it changes, and the magic display manager in Cocoa composites the resulting images. Said another way, theneedsDisplay
state (which eventually cause a new-drawRect:
message) is independent of its superview and subviews. – James BucanekdrawRect:
is responsible for subviews. I'm saying that if I have a view B which is drawn viadrawRect:
on a layer-backed view A, then my view B doesn't have itsdrawRect:
called when I focus or unfocus the window. Descendants of layer-backed views become layer-backed, too, thus the documentation quoted indicatesdrawRect:
will not be called. If I don't add a layer to view A, then my view BdrawRect:
is called when needed. – balthisarNSView
simply observe its window'sNSWindowDidBecomeMainNotification
and 'NSWindowDidResignMainNotification` notifications and send aneedDisplay=YES
message to all of its subviews? Seems simple (and harmless) enough. – James BucanekNSView
, unless I want to fork the framework. If I can find a generic solution, then I think a PR would be welcomed, but mostly I'm trying to find the cause and solution for the difference in behavior. There's a difference between hacking it to work, and figuring out what the difference is and doing it the right way. I'm not a paid pro, so I'd prefer to understand what's happening rather than just brute force it. – balthisarNSView
. Any object can observer a notification and take some action (your window controller, for example). If you think the framework controls are misbehaving when inside a layer-backed view, then definitely file a bug report. But I suspect there's a hack involved... – James Bucanek