我有以下启动和停止计时器的代码.

private var timer: Timer? = nil

private func startTimer() {
    if (timer != nil) {
        return
    }
    logger.error("Starting timer on \(Thread.current)")
    timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true, block: { timer in
        self.logger.error("Timer fired on \(Thread.current)")
    })
}

private func stopTimer() {
    if (timer == nil) {
        return
    }
    logger.error("Stopping timer on \(Thread.current)")
    timer?.invalidate()
    timer = nil
}

计时器将多次启动和停止.我遇到了一个问题,它第一次按预期开始和停止,但第二次启动计时器时,它永远不会触发.下面是我从应用程序的两次连续运行中看到的日志(log).您可以看到,在第二次运行计时器后,从未调用过"Timer fired".

运行1:

Starting timer on <_NSMainThread: 0x2829e4140>{number = 1, name = main}
Timer fired on <_NSMainThread: 0x2829e4140>{number = 1, name = main}
Timer fired on <_NSMainThread: 0x2829e4140>{number = 1, name = main}
Timer fired on <_NSMainThread: 0x2829e4140>{number = 1, name = main}
Stopping timer on <_NSMainThread: 0x2829e4140>{number = 1, name = main}
Starting timer on <NSThread: 0x2829ecf00>{number = 10, name = (null)}

运行2:

Starting timer on <_NSMainThread: 0x281cb8400>{number = 1, name = main}
Timer fired on <_NSMainThread: 0x281cb8400>{number = 1, name = main}
Timer fired on <_NSMainThread: 0x281cb8400>{number = 1, name = main}
Stopping timer on <_NSMainThread: 0x281cb8400>{number = 1, name = main}
Starting timer on <NSThread: 0x281cbc140>{number = 8, name = (null)}

为什么计时器不会在第二次计时器响起?目前我能想到的唯一潜在的领先优势就是线索.现在,计时器的停止和随后的重新启动可能不会在主线程上发生,并且Invalify()的文档说明应该在启动计时器的同一线程上调用它.因此,另一个问题是,我如何确保在同一线程上调用了Start和Stop(不必是主线程)?谢谢

推荐答案

这里有很多问题.其中之一是,在某些情况下,您的锁无法达到unlock().如果调用startTimer两次,我预计这将永远阻塞.但这不太可能是你的根本问题.

您的潜在问题正如您所预期的那样:您在错误的线程上调用了scheduledTimerinvalidate.规则是(A)必须在同一线程上调用它们,以及(B)该线程必须具有活动的RunLoop(这并不总是可用的).确保发生这种情况的最简单方法是始终在主队列上运行计时器操作.这样做,你就可以摆脱timerLock.

private func startTimer() {
    Task { @MainActor in
        if (timer != nil) {
            return
        }
        logger.error("Starting timer on \(Thread.current)")
        timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true, block: { timer in
            self.logger.error("Timer fired on \(Thread.current)")
        })
    }
}

对于stopTimer也是如此.

Swift相关问答推荐

是否可以将字典项绑定到文本字段?

为什么我的引用类型对象在初始化后有3个强引用?

SWIFT Vapor控制台应用程序-操作无法完成.权限被拒绝

通常从数组调用的SWIFT静态协议函数

为什么ClosedRange<;Int&>包含的速度比预期慢340万倍?

从任务中打印

expose 不透明的底层类型

SwiftUI路径平滑连接两条线

为什么 UITapGestureRecognizer 对于 Swift 集合视图中的单元格图像无法正常工作?

如何在 switch case 模式语句中使用 Swift 文字正则表达式?

Pod lib lint 命令找不到 watchos 模拟器

响应 UITextField (UIViewRepresentable) 中的特定按键

SwiftUI 中的计时器崩溃屏幕

如何在 RxSwift 中获取 controlEvent 类型?

Vapor 4,如何按外键过滤?

是否可以在 Swift 中创建通用闭包?

使 struct 可散列?

在 Swift for iOS 中沿圆形路径绘制文本

修复 Swift 3 中的警告C-style for Statement is deprecated

Swift 中的 recursiveDescription 方法?