5

I have this quartz class that works fine on iOS and draws an orange pizza slice style graph over a gray circle and I am trying to convert it to cocoa.

+ (UIImage *)circleWithDiameter:(CGFloat) diameter color:(UIColor *)color progress:(CGFloat)progress { CGFloat radius = diameter/2.0f; CGFloat scale = [[UIScreen mainScreen] scale]; // we need to size the graphics context according to the device scale CGRect rect = CGRectMake(0.0f, 0.0f, diameter, diameter); UIGraphicsBeginImageContextWithOptions(rect.size, NO, scale); CGContextRef context = UIGraphicsGetCurrentContext(); // create a gray circle background CGContextSetLineWidth(context, 0); // set the line width CGContextSetFillColorWithColor(context, color.CGColor); CGContextBeginPath(context); CGContextAddEllipseInRect(context, rect); CGContextDrawPath(context, kCGPathFill); // Or kCGPathFill // Draw the slice CGFloat angle = progress * 2.0f * M_PI; CGPoint center = CGPointMake(radius, radius); CGContextBeginPath(context); CGContextMoveToPoint(context, center.x, center.y); CGPoint p1 = CGPointMake(center.x + radius * cosf(angle), center.y + radius * sinf(angle)); CGContextAddLineToPoint(context, p1.x, p1.y); CGContextMoveToPoint(context, center.x, center.y); CGContextAddArc(context, center.x, center.y, radius, 0.0f, angle, 0); CGContextClosePath(context); UIColor *orange = [UIColor orangeColor]; CGContextSetFillColorWithColor(context, orange.CGColor); CGContextDrawPath(context, kCGPathFill); UIImage *result = UIGraphicsGetImageFromCurrentImageContext(); CGContextRelease(context); return result; } 

This is the class I have converted to cocoa.

+ (NSImage *)circuloWithDiameter:(CGFloat)diameter color:(NSColor *)color progress:(CGFloat)progress { CGFloat radius = diameter/2.0f; CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort]; // draw the gray circle background CGContextSetLineWidth(context, 0); // set the line width CGContextSetFillColorWithColor(context, color.CGColor); CGContextBeginPath(context); CGContextAddEllipseInRect(context, rect); CGContextDrawPath(context, kCGPathFill); // Or kCGPathFill // draw the orange slice CGFloat angle = progress * 2.0f * M_PI; CGPoint center = CGPointMake(radius, radius); CGContextBeginPath(context); CGContextMoveToPoint(context, center.x, center.y); CGPoint p1 = CGPointMake(center.x + radius * cosf(angle), center.y + radius * sinf(angle)); CGContextAddLineToPoint(context, p1.x, p1.y); CGContextMoveToPoint(context, center.x, center.y); CGContextAddArc(context, center.x, center.y, radius, 0.0f, angle, 0); CGContextClosePath(context); NSColor *orange = [NSColor orangeColor]; CGContextSetFillColorWithColor(context, orange.CGColor); CGContextDrawPath(context, kCGPathFill); CGImageRef imageRef = CGBitmapContextCreateImage(context); NSImage* result = [[NSImage alloc] initWithCGImage:imageRef size:NSMakeSize(diameter, diameter)]; CFRelease(imageRef); CGContextRelease(context); return result; } 

Apparently the conversion goes fine and Xcode is not whining about anything but when the cocoa version runs, it crashes on the line

 CGImageRef imageRef = CGBitmapContextCreateImage(context); 

with the message

<Error>: CGBitmapContextCreateImage: invalid context 0x600000160180. This is a serious error. This application, or a library it uses, is using an invalid context and is thereby contributing to an overall degradation of system stability and reliability. This notice is a courtesy: please fix this problem. It will become a fatal error in an upcoming update. 

what is wrong? any clues?

7
  • In iOS, the context is created by UIGraphicsBeginImageContextWithOptions(rect.size, NO, scale);, but it seems that the OSX code doesn't create a context before you fetch it [NSGraphicsContext currentContext]. Commented Dec 23, 2014 at 1:50
  • isn't this line CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort]; creating one? Commented Dec 23, 2014 at 1:52
  • No, it fetches the current context if exists. Commented Dec 23, 2014 at 1:56
  • what is the cocoa equivalent to UIGraphicsBeginImageContextWithOptions(rect.size, NO, scale);? Commented Dec 23, 2014 at 1:58
  • See this link, I don't have any experience on OSX, hope it work, + (NSGraphicsContext *)graphicsContextWithAttributes:(NSDictionary *)attributes. Commented Dec 23, 2014 at 2:02

1 Answer 1

14

The process is a little different in AppKit.

First you create an NSImage instance with the desired size. Then you use -[NSImage lockFocus] to initialize the drawing context. This replaces UIKit's UIGraphicsBeginImageContextWithOptions function.

From this point, your drawing code is the same as UIKit, using [[NSGraphicsContext currentContext] graphicsPort] to get the current CGContextRef.

When you finish drawing, use -[NSImage unlockFocus] to dispose of the current CGContextRef. You can then return the NSImage instance you created at the start of the function.

Sign up to request clarification or add additional context in comments.

1 Comment

FANTASTIC! IT works. The only difference is that you don't need to dispose the context at the end. THANKS!!!!!!!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.