Search code examples
iosxcodeswiftdrawinglines

Drawing performance with Swift in Xcode for iOS app


I have a function for drawing lines, edited below. It seems to work fine in the simulator, however there are performance issues, lines drawn slowly, when running on both an older iPhone (2011) and a newer iPad (2014). I believe this issue is due to creating a new CGContext for every touchesMoved event received.

How can I, for example, call let context = UIGraphicsGetCurrentContext() once when touchesBegan? (i.e. how can I make context a public variable that can be called once?)

Any other tips for improving the performance would be appreciated. Thank you.

override func touchesMoved(touches: NSSet, withEvent event: UIEvent) {

    autoreleasepool {

    UIGraphicsBeginImageContextWithOptions(view.frame.size, false, 0.0)

    let context = UIGraphicsGetCurrentContext()

    ...
    ...
    ...

    UIGraphicsEndImageContext()

    }

}

Solution

  • Do not execute drawing code in touchesMoved. You should store whatever you need to update your drawing (probably touch location), then call setNeedsDisplay. That will force a call to drawRect: which would contain all of your drawing code. You do not need to create a context, just use UIGraphicsGetCurrentContext().

    Here is a contrived UIView subclass example that draws a red circle underneath the latest touch point.

    class DrawView: UIView {
    
      let circleSize:CGFloat = 50.0
      var lastTouchPoint:CGPoint?
    
      override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        lastTouchPoint = touches.first?.locationInView(self)
        self.setNeedsDisplay()
      }
    
      override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
        lastTouchPoint = touches.first?.locationInView(self)
        self.setNeedsDisplay()
      }
    
      override func drawRect(rect: CGRect) {
        if let touchPoint = lastTouchPoint {
          let context = UIGraphicsGetCurrentContext()
          CGContextSetRGBFillColor (context, 1, 0, 0, 1);
          CGContextFillEllipseInRect(context, CGRectMake(touchPoint.x - circleSize/2.0, touchPoint.y - circleSize/2.0, circleSize , circleSize))
        }
      }
    }