1

I have a class that displays a custom indeterminate progress indicator. Each timer update it simply increments the rotation of a UIImageView using CGAffineTransformRotate.

This all works, however, I noticed that when it is running, the background process that it is waiting for runs 50% slower - which is a huge penalty. For instance; instead of taking say 20 seconds to complete the processing it takes 30 seconds. Can someone recommend a solution with less performance penalty?

func show() {
    timer?.invalidate()
    timer = NSTimer.scheduledTimerWithTimeInterval(0.03, target: self, selector: #selector(self.updateTimer(_:)), userInfo: nil, repeats: true)
}

func updateTimer(sender: NSTimer) {
    iconView.transform = CGAffineTransformRotate(iconView.transform, 0.15)
}
Jeshua Lacock
  • 5,730
  • 1
  • 28
  • 58

2 Answers2

1

Use Core Animation to animate the rotation. The window server will do all the work outside of your app's process.

let animation = CABasicAnimation(keyPath: "transform.rotation")
animation.fromValue = 0
animation.toValue = 2 * M_PI
animation.repeatCount = .infinity
animation.duration = 1.25
iconView.layer.addAnimation(animation, forKey: animation.keyPath)
rob mayoff
  • 375,296
  • 67
  • 796
  • 848
0

I think you can use dispatch_source from @Rob's answer:

Do something every x minutes in Swift

Here is the code:

var timer: dispatch_source_t!

func startTimer() {
    let queue = dispatch_queue_create("com.domain.app.timer", nil)
    timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue)
    dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 60 * NSEC_PER_SEC, 1 * NSEC_PER_SEC) // every 60 seconds, with leeway of 1 second
    dispatch_source_set_event_handler(timer) {
        // do whatever you want here
    }
    dispatch_resume(timer)
}

func stopTimer() {
    dispatch_source_cancel(timer)
    timer = nil
}
Community
  • 1
  • 1
wm.p1us
  • 2,019
  • 2
  • 27
  • 38