2017-03-02 126 views
2

我有一個倒數計時器到一個特定的日期。它看起來不錯,每秒更新一次以顯示倒計時。下面是我用來創建計時器代碼:創建一個計時器,每秒鐘運行一次?

func scheduleTimeLabelsUpdateTimer() { 

    var components = Calendar.current.dateComponents([.day, .hour, .minute, .second], from: Date()) 
    components.second! += 1 

    let nextSecondDate = Calendar.current.date(from: components)! 

    let timer = Timer(fireAt: nextSecondDate, interval: 1, target: self, selector: #selector(updateTimeLabels), userInfo: nil, repeats: true) 

    RunLoop.main.add(timer, forMode: .commonModes) 

} 

不過,我想它在第二更新每一秒,使在同一時間每個第二時鐘更新經過。現在,它會在調用此方法時每秒更新一次,這在viewDidLoad()中。

例如,如果倒計時設置爲午夜,我希望它恰好在午夜時點到零。現在它可能會在午夜後略微達到零,這取決於用戶打開此屏幕時的時間差。

編輯:這是如何倒計時顯示給用戶。 updateTimeLabels()只是根據在該日期之前剩餘的時間量設置每個標籤的文本。我希望每一個標籤都能在每一秒完全更新。這樣倒計時將準確地按時「打零」。注意現在如何,秒數達到零,然後狀態欄上的系統時鐘更新。我希望這些發生在同一時間。

enter image description here

此代碼,這是我幾個月前發現某處的堆棧溢出,被稱爲updateTimeLabels()來計算剩餘時間:

public func timeOffset(from date: Date) -> (days: Int, hours: Int, minutes: Int, seconds: Int) { 
    // Number of seconds between times 
    var delta = Double(self.seconds(from: date)) 

    // Calculate and subtract whole days 
    let days = floor(delta/86400) 
    delta -= days * 86400 

    // Caluclate and subtract whole hours 
    let hours = floor(delta/3600).truncatingRemainder(dividingBy: 24) 
    delta -= hours * 3600 

    // Calculate and subtract whole minutes 
    let minutes = floor(delta/60.0).truncatingRemainder(dividingBy: 60) 
    delta -= minutes * 60 

    // What's left is seconds 
    let seconds = delta.truncatingRemainder(dividingBy: 60) 

    return (Int(days), Int(hours), Int(minutes), Int(seconds)) 
} 
+0

你是什麼意思命中零? –

+0

倒數計時器顯示特定日期之前的天數,小時數,分鐘數和秒數。如果日期設定爲今晚午夜,那麼我希望所有這些標籤在今晚變成午夜時都準確地說出「0」,而不是一秒鐘之後的一部分。 – CompC

+0

它現在的行爲如何? –

回答

0

由於Timer被安排在運行循環其他事情正在運行循環中發生,這並不是特別準確;它會在經過指定的時間間隔後激發,但當間隔已過時,不一定恰好爲

而不是試圖爲所需的時間安排計時器,你應該運行你的計時器超過1秒,比如說0.5秒,並且每當定時器觸發時更新你的剩餘時間標籤。這將使一個平滑的更新顯示:

var timer: Timer? 

func scheduleTimeLabelsUpdateTimer() { 

self.timer = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { (timer) in 
     self.updateTimeLabels() 
    } 
} 

UPDATE

不要做這些數學; iOS內置了很好的庫來爲你完成所有這些工作;只需創建您的目標日期並使用DateComponents爲您解決。

import UIKit 

class ViewController: UIViewController { 

    @IBOutlet weak var label: UILabel! 
    @IBOutlet weak var countDownLabel: UILabel! 

    let dateFormatter = DateFormatter() 

    var targetTime: Date! 
    var calendar = Calendar.current 
    var timer: Timer? 

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

     var components = DateComponents() 

     components.setValue(3, for: .month) 
     components.setValue(3, for: .day) 
     components.setValue(2017, for: .year) 
     components.setValue(0, for: .hour) 
     components.setValue(0, for: .minute) 
     components.setValue(1, for: .second) 


     self.targetTime = calendar.date(from: components) 


     self.timer = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true, block: { (timer) in 

      self.updateLabel() 

     }) 

     self.dateFormatter.timeStyle = .long 
     self.dateFormatter.dateStyle = .short 
    } 

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

    func updateLabel() { 
     let now = Date() 
     self.label.text = self.dateFormatter.string(from: now) 


     let components = calendar.dateComponents([.day,.hour,.minute,.second], from: now, to: self.targetTime) 

     self.countDownLabel.text = String(format: "%d days %d hours, %d minutes %d seconds", components.day!, components.hour!, components.minute!,components.second!) 

    } 


} 
+0

這似乎並不奏效......它仍然和以前一樣。 – CompC

+0

你能展示更多代碼嗎?你如何追蹤剩餘時間?你如何更新標籤?你究竟看到了什麼? – Paulw11

+0

我在原帖中增加了更多細節。要更新標籤,我正在計算剩餘時間,然後在每個標籤上設置文本。 – CompC

0

在你的代碼,你當你初始化你的組件

所以定時器將總是打在輪第二個數字永遠不會使用納秒。

我測試下方打印Date()你的代碼中選擇enter image description here

我不知道這是否是你所談論的「打零」是什麼,希望這將有助於

相關問題