NSView subclass - drawRect: not called

I created a subclass of NSView called DAView that includes an array of useful methods for later reuse. This works fine, however drawRect: never DAView called in any classes that use DAView , nor in the class itself. Why?

Here's what DAView looks DAView :

DAView

@interface DAView : NSView

 - (id)initWithFrame:(NSRect)frame { self = [super initWithFrame:frame]; if (self) { self.backgroundColor = [NSColor clearColor]; // Make layer-backed by default self.wantsLayer = YES; // Create a root layer CALayer *_rootLayer = [CALayer layer]; _rootLayer.shouldRasterize = YES; _rootLayer.name = DAViewRootLayerDefaultName; self.layer = _rootLayer; } return self; } - (void)drawRect:(NSRect)dirtyRect // never called { NSLog(@"Draw Rect called"); } 

Now, if I wanted to use these DAView's add-ons / methods, I am facing the same problem. Everything works fine, except for drawRect: which, as in the case of DAView , is never called:

Datableview

@interface DATableView : DAView

 - (void)drawRect:(NSRect)dirtyRect // never called either { [[NSColor grayColor] set]; NSBezierPath *_cellSeparator = [NSBezierPath bezierPath]; [_cellSeparator lineToPoint:dirtyRect.origin]; [_cellSeparator closePath]; [_cellSeparator stroke]; NSLog(@"Draw rect"); } 

However, if I change the DATableView title as a subclass of NSView , drawRect: called. What am I missing?

+4
source share
2 answers

you need to set the _rootLayer delegate to self .

EDIT How it works for me:

 - (id)initWithFrame:(NSRect)frame { self = [super initWithFrame:frame]; if (self) { self.wantsLayer = YES; self.layer = [self makeBackingLayer]; [self.layer setDelegate:self]; } return self; } - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx { NSRect rect = self.bounds; rect.origin.x = 0; rect.origin.y = 0; [self drawRect:rect]; } 
+4
source

From the docs:

"The order that setsWantsLayer: and setLayer: is called is it makes a distinction between a level-supported view and a layer-level view."

"A layer-supported view is a view that is supported by a basic animation layer. Any drawing made with a view is cached at the background level. You set up a layer-supported view by calling setWantsLayer: with a value of YES The view class automatically creates a backup layer for you ( using makeBackingLayer, if overridden), and you should use the drawing classes of the view classes. When using layer-based views, you should never interact directly about with a layer. Instead, you should use the standard kind of programming. "

“A hosting layer is a view that contains a Core Animation layer that you intend to manipulate directly. You create a host-level view by instantiating a class of the Core Animation class and exposing this layer to the setLayer method: After that, you call setWantsLayer: with a value of YES. This the order of the methods is critical.When using a layer-level view, you should not rely on the view to draw, nor should you add a subview to the layout-level view. The one set by setLayer :) should be considered the root layer of the layer tree and you should use only Core Animation drawings and animations. You are still using the view to handle mouse and keyboard events, but any resulting artwork should be handled by Core Animation. "

Since you are supplying your own layer, instead of wanting Cocoa to create it for you, try it this way.

  // Create a root layer CALayer *_rootLayer = [CALayer layer]; _rootLayer.shouldRasterize = YES; _rootLayer.name = DAViewRootLayerDefaultName; self.layer = _rootLayer; // Make layer-backed by default self.wantsLayer = YES; 

Or, alternatively, take the one that Cocoa gives you and not create your own.

+8
source

Source: https://habr.com/ru/post/1482735/


All Articles