Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/104.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios Swift-计划计时器秒表时间部分不工作_Ios_Swift_Nstimer - Fatal编程技术网

Ios Swift-计划计时器秒表时间部分不工作

Ios Swift-计划计时器秒表时间部分不工作,ios,swift,nstimer,Ios,Swift,Nstimer,请放心,我一周前学会了Swift和Xcode(我正在创建一个应用程序,以便在假期学习Swift) 我使用scheduledTimer创建了一个计时器作为秒表。秒和分都很好,但我没时间工作。我做错了什么 currentTime = 0 timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in self.currentTime += 1 let hoursPortion = String(f

请放心,我一周前学会了Swift和Xcode(我正在创建一个应用程序,以便在假期学习Swift)

我使用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)"
}

这不是最好的方法,因为计时器不能保证足够准确,它会随时间漂移。更好的方法是记录开始时间,并使用日历功能为您提供经过的时间。e、 g

        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)"
        }

这不是最好的方法,因为计时器不能保证足够准确,它会随时间漂移。更好的方法是记录开始时间,并使用日历功能为您提供经过的时间。e、 g

        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)"
        }

正如其他人所说,你不应该自己去记录时间。让系统计算出经过了多少时间。我也倾向于为您设置字符串格式:

@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()
}

顺便说一句,这是一个微妙的点,但请注意在
计时器的捕获列表中使用了
[弱自我]
。如果没有这一点,则会出现强引用循环的变化,因为计时器在
使其无效之前不会停止,但在解决计时器对视图控制器的强引用之前,无法调用视图控制器的
deinit
。通过在闭包中使用
[weak self]
捕获列表,我们打破了这个循环,允许在视图控制器被解除时释放它,它将为您停止计时器。

正如其他人所说,您不应该自己跟踪时间。让系统计算出经过了多少时间。我也倾向于为您设置字符串格式:

@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()
}

顺便说一句,这是一个微妙的点,但请注意在
计时器的捕获列表中使用了
[弱自我]
。如果没有这一点,则会出现强引用循环的变化,因为计时器在
使其无效之前不会停止,但在解决计时器对视图控制器的强引用之前,无法调用视图控制器的
deinit
。通过在闭包中使用
[弱自我]
捕获列表,我们打破了这个循环,允许在视图控制器被解除时释放它,它将为您停止计时器。

如果当前时间已过秒,则小时数为
currentTime/3600
。我不知道你为什么要乘以20。无论如何,这种方法可能不是最好的;计时器不准确。更好的方法是在秒表启动时创建一个
日期
,并计算该日期与计时器计时时的“现在”之间的差值
DateComponents
可以帮助您从日期获取字段。是的,这是真的,20应该是3600,但我将其设置为20,这样我就不必等待一个小时来查看它是否有效。我将HoursPart设置为乘法,因为我认为1小时=3600秒。不,你想除法,因为1小时=3600秒;如果
currentTime
=3600,则为1小时,因此
currentTime/3600
如果当前时间已过秒,则小时为
currentTime/3600
。我不知道你为什么要乘以20。无论如何,这种方法可能不是最好的;计时器不准确。更好的方法是在秒表启动时创建一个
日期
,并计算该日期与计时器计时时的“现在”之间的差值
DateComponents
可以帮助您从日期获取字段。是的,这是真的,20应该是3600,但我将其设置为20,这样我就不必等待一个小时来查看它是否有效。我将HoursPart设置为乘法,因为我认为1小时=3600秒。不,你想除法,因为1小时=3600秒;如果
currentTime
=3600,则这是1小时,因此
currentTime/3600
感谢您的宝贵意见!我并没有在我正在做的项目中使用它,但我正在测试一些东西,并让它开始工作。如何设置计时器的格式,使其显示00:02:20,持续2分20秒?请使用您在初始问题中使用的字符串(格式:)方法,或使用Rob提供的DateComponents格式建议。感谢您的宝贵意见!我并没有在我正在做的项目中使用它,但我正在测试一些东西,并让它开始工作。如何设置计时器的格式,使其显示00:02:20,持续2分20秒?使用您在初始问题中使用的字符串(格式:)方法,或使用Rob提供的DateComponents格式建议。