Search code examples
iosswiftcore-graphics

swift - error when drawing curve


I am attempting to write a program that draws a curve. The shorter the curve, the closer to green it gets. Here is the code for drawing the circle:

func drawCircle(percent: CGFloat) {
    // Set up all the data for the circle
    let redAmt = 1 / 100 * percent
    let greenAmt = 1 - redAmt
    let circleColor = UIColor.init(red: redAmt, green: greenAmt, blue: 0, alpha: 1)
    let lineWidth = CGFloat(12)
    let centerX = self.frame.size.width / 2
    let centerY = self.frame.size.height / 2
    let radius = (self.frame.size.width - lineWidth) / 2
    // Clear the area where the circle is going to be drawn
    let clearCirclePath = UIBezierPath(arcCenter: CGPoint(x: centerX, y: centerY), radius: radius, startAngle: CGFloat(0), endAngle: CGFloat(M_PI * 2), clockwise: true)
    clearColor.setStroke()
    clearCirclePath.lineWidth = lineWidth
    clearCirclePath.stroke()
    // Draw the circle
    let circlePath = UIBezierPath(arcCenter: CGPoint(x: centerX, y: centerY), radius: radius, startAngle: CGFloat(0), endAngle: CGFloat(M_PI * 2) * percent / 100, clockwise: true)
    circleColor.setStroke()
    circlePath.lineWidth = lineWidth
    circlePath.stroke()
}

It works just fine when called by drawRect(rect: CGRect), but when I try to call in another file, it does not work. It is drawing the arc in a view inside a view controller. The error it gives me is this: ExerciseTracker[7270] <Error>: CGContextSetStrokeColorWithColor: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.

Thanks a lot!

(I am using Xcode 7.3.1)


Solution

  • You must draw in a valid context. drawRect: provides such a valid context. Simply putting code outside of drawRect: doesn't work unless you explicitly create your own context such as a bitmap context for creating an image by drawing.

    The code in your drawCircle method needs to be in the drawRect: method of a custom view class. Instead of passing percent as a parameter, set it as an instance variable. Then anytime you update the value of percent, you call setNeedsDisplay() to trigger the view to redraw itself.