简体   繁体   中英

Swift timer delay not pausing execution

I have made a timer in swift that will update a GUI (not included in code) every 0.01 seconds. In the code that is being repeatedly called i have it set to invalidate the timer when it has reached that target amount of time. I was expecting it to not return to the main function until the timer is done, however while the timer is still running the commands on the main() function will still continue to execute. I have condensed the code into a small example that should still produce the problem. If there are any errors or you want more of the code please let me know. Here is the code:

import UIKit

class TimerTestFile: UIViewController {
var dataObject: String = ""

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    main()
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)
}

func updateTime() {

    let currentTime = NSDate.timeIntervalSinceReferenceDate()

    //Find the difference between current time and start time.

    var elapsedTime: NSTimeInterval = currentTime - startTime

    //calculate the minutes in elapsed time.

    let minutes = UInt8(elapsedTime / 60.0)

    elapsedTime -= (NSTimeInterval(minutes) * 60)

    //calculate the seconds in elapsed time.

    let seconds = UInt8(elapsedTime)

    elapsedTime -= NSTimeInterval(seconds)

    //find out the fraction of milliseconds to be displayed.

    let fraction = UInt8(elapsedTime * 100)

    //add the leading zero for minutes, seconds and millseconds and store them as string constants
    let strSeconds = String(format: "%02d", (UInt8(targetSeconds) - seconds))

    if seconds == UInt8(targetSeconds) {
        timer.invalidate()
    }

    /* --GUI ONLY-- timerLabel.text = strSeconds
    let percentNum = (Float(seconds) + Float(fraction) / 100)
    print (percentNum)
    let percent = Float(percentNum) / Float(targetSeconds)
    print(percent)
    progressBar.setProgress(Float(percent), animated: true) */

}

func Timer(Seconds: Int) {
    progressBar.setProgress(0.0, animated: false)
    targetSeconds = Seconds
    let aSelector : Selector = #selector(TimerTestFile.updateTime)
    timer = NSTimer.scheduledTimerWithTimeInterval(0.01, target: self, selector: aSelector, userInfo: nil, repeats: true)
    startTime = NSDate.timeIntervalSinceReferenceDate()
}

func main() {
    Timer(5)
    //This timer is not delayed until the proir is done
    Timer(5)
}


}

A computer is able to perform tasks much faster than one command every millisecond (0.01 seconds).

First, you schedule the timer, which will first fire in 0.01 seconds. In the meantime, execution returns to whatever was happening before (the Timer method which then returns to the main method.) When the Timer does fire, as soon as it is done there is another few microseconds that the computer may utilize to run other code on the main thread.

Moral of the story is that in those gaps of time when your Timer is not firing, execution returns elsewhere.

Also, if you need this GUI to still update when the user is interacting with the UI, for example when they are scrolling or something similar, you will need to explicitly add your NSTimer to the main run loop with common modes after creating it using an initializer instead of the scheduledTimer method, as described here (albeit in Objective-C).

Side Note: consider changing your Timer method. In the upcoming version of Foundation , NSTimer has been renamed to Timer in Swift and your function sort of looks like it could be an initializer. Also, method names and properties should be lowercase in Swift.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM