将一个Quartz方法从iOS转换到OSX

5

我有一个Quartz类,在iOS上运行良好,可以在灰色圆圈上绘制橙色的披萨片样式图表,现在我正在尝试将其转换为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;

}

这是我已经转换成 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;

}

显然,转换过程很顺利,Xcode没有抱怨任何问题,但当Cocoa版本运行时,它会在该行崩溃。

  CGImageRef imageRef = CGBitmapContextCreateImage(context);

带有消息

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

出了什么问题?有线索吗?


在iOS中,上下文是通过UIGraphicsBeginImageContextWithOptions(rect.size, NO, scale);创建的,但似乎OSX代码在获取它之前不会创建上下文[NSGraphicsContext currentContext] - KudoCC
这行代码 CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort]; 不是在创建一个上下文吗? - Duck
不,如果上下文存在,它会获取当前的上下文。 - KudoCC
看这个链接,我没有任何在OSX上的经验,希望它能工作,+ (NSGraphicsContext *)graphicsContextWithAttributes:(NSDictionary *)attributes - KudoCC
我遇到了同样的问题。你能发一下解决后的代码吗? - YeahStu
显示剩余2条评论
1个回答

13

在AppKit中,这个过程略有不同。

首先,您需要创建一个指定大小的NSImage实例。然后,您可以使用-[NSImage lockFocus]初始化绘图上下文。这替代了UIKit的UIGraphicsBeginImageContextWithOptions函数。

从这一点开始,您的绘图代码与UIKit的相同,使用[[NSGraphicsContext currentContext] graphicsPort]来获取当前的CGContextRef

完成绘制后,请使用-[NSImage unlockFocus]来处理当前的CGContextRef。然后您可以返回在函数开头创建的NSImage实例。


太棒了!它能正常工作。唯一的区别是你不需要在最后释放上下文。谢谢!!!!! - Duck

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接