2

I have a few lines of drawing code that are duplicated in two different subclasses. When I move this drawing code to its own class and then call it from within drawRect: it is called but it is never drawn to the screen. What is the right way prevent duplicating code in two different drawRect: methods?

Details: I'm making a custom control by subclassing NSTableView and NSTableCellView. My drawing code needs to be in drawRect: in both of these subclasses.

I created a subclass of NSObject that declares one method. Here is the implementation:

@implementation TNLChartDrawingExtras

- (void)drawDividersInRect:(NSRect)rect startingAtDate:(NSDate *)startDate withZoomFactor:(NSNumber *)zoomFactor {

    float pos = 0;
    NSDate *currentDate = [startDate copy];

    while (pos < rect.size.width) {

        //draw the vertical divider
        NSBezierPath *linePath = [NSBezierPath bezierPathWithRect:NSMakeRect(pos, 0.0, 1.0, rect.size.height)];
        [[NSColor colorWithCalibratedWhite:0.85 alpha:0.5] set];
        [linePath fill];

        //increment the values for the next day
        currentDate = [NSDate dateWithTimeInterval:86400 sinceDate:currentDate]; // add one day to the current date
        pos = pos + (86400.0/ [zoomFactor floatValue]);
    }
}

In my NSTableView subclass I define a property for this object. Then in awakeFromNib I create an instance of this class:

- (void)awakeFromNib {
    self.extras = [[TNLChartDrawingExtras alloc] init];
}

In drawRect: I send this message:

- (void)drawRect:(NSRect)dirtyRect {
    // more code here...

    [self.extras drawDividersInRect:viewBounds startingAtDate:chart.startDate withZoomFactor:self.zoomFactor];
}

The code is executed but the lines it is supposed to draw don't appear. If I put the code from drawDividersInRect:... in the drawRect: method, it works fine.

4

2 回答 2

1

My original solution (described in the question) may have worked if I had continued to debug it. However, I think the more important question is what is the right way to approach this problem. Here I solve it by adding category on NSView to the project:

I'm trying to add custom drawing code to both NSTableView and NSTableCellView. Both are subclasses of NSView so I created a category of NSView and added my custom drawing method there. Now I can call my drawing method from both subclasses.

于 2012-12-19T08:40:36.527 回答
0

Without see any of your code, it sounds like you are in need of a protocol, which is that same thing as an interface in the java language. Protocols are a series of methods that a group of a few unrelated classes may need to used. For example, in a drawing program like PhotoShop, Rects, Ovals, and Images are all valid objects that can be stored as layers in a .psd document, however, they all share traits like the ability to change object properties in a particular way. An example would be adjusting an objects' opacity or rescale an objects size, etc. Methods that access the objects properties for scaling or functions that can be shared between unrelated objects types call for protocols.

They are essentially .h files that list out the methods. The .m file that defines implementation of the code can store a tag in it's .h file.

// example of a class that acts as a protocol implementor
@interface LayerObject: NSObject <Resizable>

The tag says, "I am a member of the protocol named X, you can find one/some of the methods of protocol X in my .m file." All you would have to do is import the protocol to the desired classes using the following syntax:

// Declare protocol
@protocol Resizable;
// List methods wanted from protocol
- id resizeRect: id layerObject;

to gain the methods defined in the protocol.

Here is a website that describes protocols through an example: http://agilewarrior.wordpress.com/2012/03/19/simple-objective-c-protocol-example/

Another solution would be to create a class hierarchy that uses an abstract class to put the given drawRect method you are working in. From here you could define the two subclass you are working on as a subclass of the abstract class in which they would inherit the drawRect method code, keeping you from repeating the code in two separate classes.

于 2012-12-19T05:45:39.623 回答