Swift - UIProgressView is not smooth with NSTimer

dwinnbrown picture dwinnbrown · Jul 15, 2015 · Viewed 14.2k times · Source

So I am using an NSTimer to let the user know the app is working. The progress bar is set up to last 3 seconds, but when running, it displays in a 'ticking' motion and it is not smooth like it should be. Is there anyway I can make it more smooth - I'm sure just a calculation error on my part....

If anyone could take a look that would be great. Here is the code:

import UIKit

class LoadingScreen: UIViewController {


    var time : Float = 0.0
    var timer: NSTimer?

    @IBOutlet weak var progressView: UIProgressView!


    override func viewDidLoad() {
        super.viewDidLoad()

// Do stuff

timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector:Selector("setProgress"), userInfo: nil, repeats: true)

}//close viewDidLoad

  func setProgress() {
        time += 0.1
        progressView.progress = time / 3
        if time >= 3 {
            timer!.invalidate()
        }
    }

}

Answer

mbottone picture mbottone · Jul 15, 2015

Edit: A simple 3 second UIView animation (Recommended)

If your bar is just moving smoothly to indicate activity, possibly consider using a UIActivityIndicatorView or a custom UIView animation:

override func viewDidAppear(animated: Bool)
{
    super.viewDidAppear(animated)

    UIView.animateWithDuration(3, animations: { () -> Void in
        self.progressView.setProgress(1.0, animated: true)
    })
}

Make sure your progressView's progress is set to zero to begin with. This will result in a smooth 3 second animation of the progress.

Simple animated progress (Works but still jumps a bit)

https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIProgressView_Class/#//apple_ref/occ/instm/UIProgressView/setProgress:animated:

func setProgress() {
    time += 0.1
    progressView.setProgress(time / 3, animated: true)
    if time >= 3 {
        timer!.invalidate()
    }
}

Option with smaller intervals. (Not recommended)

Set your timer to a smaller interval:

timer = NSTimer.scheduledTimerWithTimeInterval(0.001, target: self, selector:Selector("setProgress"), userInfo: nil, repeats: true)

Then update your function

func setProgress() {
    time += 0.001
    progressView.setProgress(time / 3, animated: true)
    if time >= 3 {
        timer!.invalidate()
    }
}