0

I have a NSView subclass named OneView with the following code:

#import "OneView.h"

@interface OneView ()
@property (strong, nonatomic) NSGradient *gradient;
@end

@implementation OneView

- (void)drawRect:(NSRect)dirtyRect {

    [super drawRect:dirtyRect];

    NSColor *top = [NSColor colorWithCalibratedRed:1.0 green:0.0 blue:0.0 alpha:1.0];
    NSColor *btm = [NSColor colorWithCalibratedRed:0.0 green:0.0 blue:0.0 alpha:1.0];

    self.gradient = [[NSGradient alloc] initWithStartingColor:top endingColor:btm];
    [self.gradient drawInRect:self.bounds angle:270];
}

# pragma mark - Public

- (void)changeGradient {

    self.gradient = nil;

    NSColor *top = [NSColor colorWithCalibratedRed:0.0 green:1.0 blue:0.0 alpha:1.0];
    NSColor *btm = [NSColor colorWithCalibratedRed:0.0 green:0.0 blue:0.0 alpha:1.0];

    self.gradient = [[NSGradient alloc] initWithStartingColor:top endingColor:btm];
    [self.gradient drawInRect:self.bounds angle:270];

    [self setNeedsDisplay:YES];
}

@end

In my AppDelegate (or could be any other class), I am trying to change the colors of the gradient by calling the changeGradient method of the OneView class:

#import "AppDelegate.h"
#import "OneView.h"

@interface AppDelegate ()
@property (weak, nonatomic) IBOutlet OneView *oneView;
@end

@implementation AppDelegate


- (IBAction)changeGradient:(id)sender {
    [self.oneView changeGradient];
}

@end

When the view is first loaded the gradient is initialized as expected but I am unable to change the gradient from the IBAction method. I have achieved this using layer backed views but I am trying to find a way that doesn't rely on layers for backwards compatibility.

Any thoughts on why the IBAction is not changing the gradient?

enter image description here

4

2 回答 2

0

The problem is self.gradient = [[NSGradient alloc] initWithStartingColor:top endingColor:btm]; inside drawRect: function. Change it to if (!self.gradient) { self.gradient = [[NSGradient alloc] initWithStartingColor:top endingColor:btm]; } will fix the issue. By the way, you shouldn't create gradient inside your drawRect: method. It will hurt the performance. In that case, should put the initialization in awakeFromNib method.

于 2014-07-22T04:25:07.523 回答
0

Your drawRect: method is always going to draw the same thing inside it. You shouldn't try to draw outside of drawRect: You really only need to set the gradient in viewWillDraw: if the gradient is nil.

You should probably redesign to have the gradient's colors be properties of the view as well. Then use KVO to observe and respond to any color change by calling setNeedsDisplay:YES

If you need more I can post after back at computer.

于 2014-07-22T04:25:49.810 回答