VansFannel
VansFannel

Reputation: 45921

Draw a Radiant Gradient: <Error>: CGContextDrawPath: invalid context 0x0

I'm developing an iOS 5.0+ app with latest SDK.

I'm very very new on CoreGraphics and I don't know how to draw a radiant gradient on a CALayer.

I have found that I have to use CGContextDrawRadialGradient to draw a radiant gradient.

Searching on Google, I see that I have to add the radiant gradient to CALayer's content, but to draw it I need a CGContext, and I don't know how to get this CGContext.

Do you know how can I do it?

I have found this tutorial, but it also uses CGContext.

My code is this:

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController

@property (weak, nonatomic) IBOutlet UIView *testView;

@end

Implementation:

#import "ViewController.h"
#import <QuartzCore/QuartzCore.h>

@interface ViewController ()

- (void)drawRadiantGradient;

@end

@implementation ViewController

@synthesize testView = _testView;

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    [self drawRadiantGradient];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)drawRadiantGradient
{
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

    CGFloat redBallColors[] = {
        1.0, 0.9, 0.9, 0.7,
        1.0, 0.0, 0.0, 0.8
    };
    CGFloat glossLocations[] = {0.05, 0.9};
    CGGradientRef ballGradient = CGGradientCreateWithColorComponents(colorSpace, redBallColors, glossLocations, 2);
    CGRect circleBounds = CGRectMake(20, 250, 100, 100);
    CGPoint startPoint = CGPointMake(50, 270);
    CGPoint endPoint = CGPointMake(70, 300);
    CGContextDrawRadialGradient(context, ballGradient, startPoint, 0, endPoint, 50, 0);
    CGContextAddEllipseInRect(context, circleBounds);
    CGContextDrawPath(context, kCGPathStroke);
}

I want to create a CALayer, draw a radiant gradient, and add this CALayer to _testView.

Upvotes: 1

Views: 4716

Answers (3)

Tobi
Tobi

Reputation: 5519

The UIGraphicsGetCurrentContext() only return a valid context when called from sprecific methods or of you created a new one f.e. by calling UIGraphicsBeginImageContext().

So what you need to do, is either subclass a UIView and overwrite it's drawRect: method with the code in your drawRadiantGradient method. Or you could use the delegate methods provided by the CALayerDelegate protocol. Just set the layer's delegate to your vc and implement the drawLayer:inContext: method. This could look like this:

in your .h file:

@interface MyVC : UIViewController
@property (weak, nonatomic) IBOutlet UIView *drawingView;    
/...

and in your .m file:

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.drawingView.layer.delegate = self;
}

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)context
{
    [self drawRadiantGradientInContext:context];
}

Upvotes: 1

David R&#246;nnqvist
David R&#246;nnqvist

Reputation: 56625

You would either draw into your own context (for example an image context that you created using UIGraphicsBeginImageContextWithOptions()

or

become the delegate of that layer and draw into the layers graphics context using drawLayer:inContext:

It sounds to me like you want to do the second option. You would create the CALayer and set yourself as the delegate. Then implement drawLayer:inContext: and use the context the context that is passed as an argument.

Setup

CALayer *yourLayer = [CALayer layer];
// other layer customisation
yourLayer.delegate = self;

And draw

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {
    // Check that the layer argument is yourLayer (if you are the 
    // delegate to more than one layer)

    // Use the context (second) argument to draw.
}

Upvotes: 1

Peter Hosey
Peter Hosey

Reputation: 96323

Make a custom subclass of UIView that draws the gradient in its drawRect: method, and have your VC create a radial-gradient view and add that as a subview of its view.

Upvotes: 0

Related Questions