Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.3k views
in Technique[技术] by (71.8m points)

xcode - Swift timer in milliseconds

I want to change the timer every millisecond but it doesnt work as expected.

NSTimer.scheduledTimerWithTimeInterval(0.001, target: self, selector: Selector("advanceTimer:"), userInfo: nil, repeats: true);

func advanceTimer(timer: NSTimer){

    self.time += 0.001;

    let milliseconds = self.time * 100;
    let remaingMilliseconds = Int((milliseconds % 1000) / 10);
    let seconds = Int((milliseconds / 1000) % 60)

    let strSeconds = String(format: "%02d", seconds)
    let strFraction = String(format: "%02d", remaingMilliseconds)

    timerText.text = "(strSeconds):(strFraction)";

 }

The result is

The timer change up to 100 in the millisecond part (00:100) and then change to 01:00 = 40 real secs

Duncan approach:

var time: NSTimeInterval = 0;
var startTime: NSTimeInterval = 0;

//And your  timer method...
func advanceTimer(timer: NSTimer){
    //Total time since timer started, in seconds
    self.time = NSDate.timeIntervalSinceReferenceDate() - startTime
    println(self.time);
    //The rest of your code goes here
}

override func didMoveToView(view: SKView) {

    // Set anchor point
    self.anchorPoint = CGPointMake(0.5, 0.5);


    var startTime: NSTimeInterval
    //Sart the timer
    startTime = NSDate.timeIntervalSinceReferenceDate()
    NSTimer.scheduledTimerWithTimeInterval(0.02,
            target: self,
            selector: Selector("advanceTimer:"),
            userInfo: nil,
            repeats: true)
}

Result: 456680125.54539 the first print

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

As Martin says in his comment, timers have a resolution of 50-100 ms (0.05 to 0.1 seconds). Trying to run a timer with an interval shorter than that will not give reliable results. Also, timers are not realtime. They depend on the run loop they are attached to, and if the run loop gets busy, the firing of the timer gets delays.

Instead of trying to increment a counter each time your timer fires, record the start time when you initiate the timer, and then do some math to figure out how much time has transpired:

var startTime: NSTimeInterval

//Sart the timer
startTime = NSDate.timeIntervalSinceReferenceDate()
NSTimer.scheduledTimerWithTimeInterval(0.02, 
  target: self, 
  selector: Selector("advanceTimer:"), 
  userInfo: nil,
  repeats: true)


//And your  timer method...
func advanceTimer(timer: NSTimer)
{
  //Total time since timer started, in seconds
  self.time = NSDate.timeIntervalSinceReferenceDate() - startTime
  //The rest of your code goes here
 }

EDIT:

The Swift 3 version of this code looks like this:

(Written as a view controller in a test project)

class ViewController: UIViewController {

  weak var timer: Timer?
  var startTime: Double = 0
  var time: Double = 0

  @IBOutlet weak var timeValueLabel: UILabel!

  /* 
  When the view controller first appears, record the time and start a timer
  */
  override func viewDidAppear(_ animated: Bool) {
    startTime = Date().timeIntervalSinceReferenceDate
    timer = Timer.scheduledTimer(timeInterval: 0.05,
                                 target: self,
                                 selector: #selector(advanceTimer(timer:)),
                                 userInfo: nil,
                                 repeats: true)
  }

  //When the view controller is about to disappear, invalidate the timer
  override func viewWillDisappear(_ animated: Bool) {
    timer?.invalidate()
  }


  func advanceTimer(timer: Timer) {

    //Total time since timer started, in seconds
    time = Date().timeIntervalSinceReferenceDate - startTime

    //The rest of your code goes here

    //Convert the time to a string with 2 decimal places
    let timeString = String(format: "%.2f", time)

    //Display the time string to a label in our view controller
    timeValueLabel.text = timeString
  }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share
...