2017-06-14 177 views
0

包涵scheduledTimer秒錶小時部分我拿起斯威夫特和Xcode的一個星期前(IM創建一個應用程序在我的假期學習斯威夫特)斯威夫特 - 不工作

我使用scheduledTimer充當秒錶創建一個定時器。秒和分鐘運行良好,但我無法獲得工作時間。我究竟做錯了什麼?

currentTime = 0 
timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in 

    self.currentTime += 1 

    let hoursPortion = String(format: "%02d", CGFloat(self.currentTime) * 60) 
    let minutesPortion = String(format: "%02d", self.currentTime/60) 
    let secondsPortion = String(format: "%02d", self.currentTime % 60) 
    //let tenPortion = String(format: "%d", self.currentTime * 10 % 10) 
    self.TimerDisplay.text = "\(hoursPortion):\(minutesPortion):\(secondsPortion)" 
} 
+0

如果當前時間已過秒,則小時數爲'currentTime/3600'。我不知道你爲什麼乘以20.這種方法可能不是最好的;計時器不準確。更好的方法是在秒錶開始時創建一個「日期」,並在計時器計時時計算該日期與「現在」之間的差值。 'DateComponents'可以幫助您從日期獲取字段。 – Paulw11

+0

是的,這是真的20應該是3600,但我把它設置爲20,所以我不必等待一個小時,看看它是否工作。我將hoursPortion設置爲乘數,因爲我認爲1小時= 3600秒。 –

+0

不,你想劃分,因爲1小時= 3600秒;如果'currentTime' = 3600那麼這是1小時,所以'currentTime/3600' – Paulw11

回答

0

這不是最好的方法,因爲定時器不能保證足夠準確,它會隨着時間而漂移。更好的方法是記錄開始時間並使用日曆功能爲您提供已用時間。例如

 let startTime = Date() 
     let timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in 
      let now = Date() 
      let components = Calendar.current.dateComponents([.hour, .minute, .second], from: startTime, to: now) 

      guard let hoursPortion = components.hour, let minutesPortion = components.minute, let secondsPortion = components.second 
      else { 
       preconditionFailure("Should not happen") 
      } 

      self.TimerDisplay.text = "\(hoursPortion):\(minutesPortion):\(secondsPortion)" 
     } 
+0

感謝您的評論是有用的!我沒有最終將它用於我正在進行的項目,但我正在測試一些東西並使其工作。如何格式化計時器以顯示00:02:20 2分20秒? –

+0

使用您在初始問題中使用的字符串(格式:)方法,或使用Rob的DateComponentsFormatter建議。 –

1

正如其他人所說的,你不應該試圖自己跟蹤時間。讓系統判斷已經過了多長時間。而且,我會傾向於使用DateComponentsFormatter格式化字符串也適用於你:

@IBOutlet weak var elapsedLabel: UILabel! 

weak var timer: Timer? 

private var formatter: DateComponentsFormatter = { 
    let formatter = DateComponentsFormatter() 
    formatter.unitsStyle = .positional 
    formatter.allowedUnits = [.hour, .minute, .second] 
    formatter.zeroFormattingBehavior = .pad 
    return formatter 
}() 

private func startTimer() { 
    timer?.invalidate()  // stop prior timer, if any 

    let startTime = Date() 

    timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [weak self] _ in 
     self?.elapsedLabel.text = self?.formatter.string(from: startTime, to: Date()) 
    } 
} 

deinit { 
    timer?.invalidate() 
} 

順便說一句,這是一個微妙的一點,但請注意在Timer封閉的捕獲列表使用[weak self]。如果沒有這個功能,你可以改變一個強參考週期,因爲定時器不會停止,直到它們被調用,但視圖控制器的deinit只有在解決了定時器對視圖控制器的強引用之後才能被調用。通過在閉包中使用[weak self]捕獲列表,我們打破了這個循環,允許視圖控制器在被解除時釋放並且它會停止定時器。