Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling setNeedsDisplay:YES on layer-hosting view does not redraw the view

I have a layer-hosting view set up like this in a custom NSView subclass:

[self setLayer:rootLayer];
[self setWantsLayer:YES];

I add all the sublayers to the layer tree after I called setNeedsDisplay on each sublayer. Each layer's content is provided by a drawLayer:inContext method of my layer's delegate.

Here is my problem:

After initializing my view the view gets draw correctly. However, when the model has changed and I call [myCustomView setNeedsDisplay:YES]; from my view controller the drawLayer:inContext is not called.

I am confused now how to update the view:

  • Do I have to call the setNeedsDisplay method on each CALayer in the layer tree?
  • Should not the call of setNeedsDisplay:YES on the layer-hosting view itself trigger the redraw of the whole layer tree?

Thanks for your help.

Edit

I have found something in the NSView Class reference

A layer-backed view is a view that is backed by a Core Animation layer. Any drawing done by the view is the cached in the backing layer. You configured a layer-backed view by simply invoking setWantsLayer: with a value of YES. The view class will automatically create the a backing layer for you, and you use the view class’s drawing mechanisms. When using layer-backed views you should never interact directly with the layer.

A layer-hosting view is a view that contains a Core Animation layer that you intend to manipulate directly. You create a layer-hosting view by instantiating an instance of a Core Animation layer class and setting that layer using the view’s setLayer: method. After doing so, you then invoke setWantsLayer: with a value of YES. When using a layer-hosting view you should not rely on the view for drawing, nor should you add subviews to the layer-hosting view.

link to documentation

In my case I have a layer-hosting view. So does that indeed mean that I have to trigger the redraw manually? Should I implement a pseudo drawRect method in the custom NSView to call the appropriate setNeedsDisplay on the CALayers that changed?

like image 468
GorillaPatch Avatar asked Feb 03 '23 02:02

GorillaPatch


1 Answers

After further research in Apple's sample code of a kiosk-style menu I found out that if you are using a layer-hosting view, you have to take care of the screen updates which are neccessary due to model changes yourself. Calling setNeedsDisplay:YES on the NSView will not do anything.

So what one has to do if one has to update a view one should write a method like reloadData and in it one should call setNeedsDisplayon each CALayer that needs a refresh. I am still not sure if a call to this method on the root layer will propagate through all the children layers but I do not think so.

I solved the problem now by calling setNeedsDisplay on the individual CALayers that needed recaching. It works without problems.

like image 89
GorillaPatch Avatar answered Apr 29 '23 16:04

GorillaPatch