2017-06-14 103 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]捕获列表,我们打破了这个循环,允许视图控制器在被解除时释放并且它会停止定时器。