我有这样的代码调用定时器调度方法.到目前为止,我从来没有遇到过调用计时器方法的问题.我甚至没有使用RunLoop.

private func expireToken(afterTimeInterval timeInterval: TimeInterval) {
        print("[DEBUG] Schedule expiration, time: \(timeInterval), main thread \(Thread.isMainThread)")
        let timer = Timer.scheduledTimer(withTimeInterval: timeInterval, repeats: false) { timer in
            print("[DEBUG] Expiring token")
            self.tokenContainer = .expired
            timer.invalidate()
        }
        RunLoop.current.add(timer, forMode: .common)
    }

此方法似乎是从后台线程调用的,因为第一个打印语句记录了控制台的此类信息

[DEBUG] Schedule expiration, time: 10.0, main thread false

推荐答案

只能在被处理的RunLoop上调度计时器(定期调用run...个方法中的一个).大多数线程不处理RunLoop.

通常,对于您所描述的情况,正确的答案是在主运行循环上运行计时器.计时器本身就非常便宜.

有了SWIFT并发,您还可以轻松地通过任务和Task.sleep来实现这一点.这将让你.cancel()的任务就像你.invalidate()的计时器一样.我会在新代码中推荐这种方法.类似于:

private func expireToken(afterTimeInterval timeInterval: TimeInterval) {
    print("[DEBUG] Schedule expiration, time: \(timeInterval), main thread \(Thread.isMainThread)")
    // Be sure to cancel any previous expiration.
    self.expireTask?.cancel() 
    self.expireTask = Task {
        try Task.sleep(for: .seconds(timeInterval)
        // If the sleep is cancelled, the above line will throw
        // and these will not run.
        print("[DEBUG] Expiring token")
        self.tokenContainer = .expired
    }
}

您也可以使用DispatchQueue.asyncAfter在没有计时器的给定时间之后运行某项操作.

最后,如果您确实需要处理自己的后台RunLoop,请参阅《线程编程指南》中的Run Loops.然而,很少需要这样做.

作为一个无关的说明,没有必要使已经触发且不重复的计时器无效.It invalidates itself:

非重复计时器触发一次,然后自动使自身无效,从而防止计时器再次触发

Swift相关问答推荐

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

Swift:iVar + Equatable上的协议约束

如何将图像插入到矩形中

RxSwift .debounce,.throttle用于分页

如何在SwiftUI的文本视图中显示NSMutableAttributedString?

如何绑定环境变量ios17

无论玩家移动到视图内的哪个位置,如何使用 SpriteKit 让敌人向玩家emits 子弹?

使用索引来访问 libc 定义的元组

如何延迟 swift 属性 didSet 使其每秒只触发一次

与 SwiftUI 中的 onChange 修饰符相比,objectWillChangeSequence 的目的是什么?

在 SwiftUI 中的 ForEach 中使用 id 时如何为数组设置动画索引

按钮图像不会立即刷新

RealityKit – 无法加载 ARView(发现为零)

在 Swift 中,如何查看 Process() 传递给 shell 的字符串?

如何在今天的扩展(iOS)中访问 CoreData 模型

如何快速识别字符串中的大写和小写字符?

Swift 中的 CommonHMAC

如何在 Swift 中将 NSURL 转换为字符串

使用 Swift 以编程方式自定义 UITableViewCell

我可以让#selector 引用 Swift 中的闭包吗?