Search code examples
iosswiftuiprogressview

Swift - UIProgressView is not smooth with NSTimer


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()
        }
    }

}

Solution

  • 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()
        }
    }