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?
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.