首页 > 解决方案 > DispatchQueue.main.asyncAfter 带开/关开关

问题描述

我创建了以下结构,以在网络连接速度慢时提醒用户。

当一个函数要调用服务器时,它会创建一个 ResponseTimer。这会设置延迟通知,仅当 responseTimer var isOn = true 时才会触发。当我的函数得到来自服务器的响应时,设置 responseTimer.isOn = false。

这是结构:

struct ResponseTimer {

var isOn: Bool

init() {
    self.isOn = true
    self.setDelayedAlert()
}

func setDelayedAlert() {
    let timer = DispatchTime.now() + 8
    DispatchQueue.main.asyncAfter(deadline: timer) {
        if self.isOn {
            NotificationCenter.default.post(name: NSNotification.Name(rawValue: toastErrorNotificationKey), object: self, userInfo: ["toastErrorCase" : ToastErrorCase.poorConnection])
        }
    }
}

这就是我如何使用它

func getSomethingFromFirebase() {

    var responseTimer = ResponseTimer()

    ref.observeSingleEvent(of: .value, with: { snapshot in
        responseTimer.isOn = false

        //do other stuff
    })
}

即使在 8 秒延迟完成之前响应返回的情况下,仍会触发通知。我在这里做错了什么???有没有更好的模式可以用于这样的事情?

谢谢您的帮助!

标签: iosswiftgrand-central-dispatch

解决方案


更好的方法是使用DispatchSourceTimer可以取消的

var timer : DispatchSourceTimer?

func startTimer()
{
    if timer == nil {
        timer = DispatchSource.makeTimerSource(queue: DispatchQueue.global())
        timer!.schedule(deadline: .now() + .seconds(8))
        timer!.setEventHandler {
            DispatchQueue.main.async {
                NotificationCenter.default.post(name: NSNotification.Name(rawValue: toastErrorNotificationKey), object: self, userInfo: ["toastErrorCase" : ToastErrorCase.poorConnection])
            }
            self.timer = nil
        }
        timer!.resume()
    } 
}

func getSomethingFromFirebase() {

    startTimer()

    ref.observeSingleEvent(of: .value, with: { snapshot in
         self.timer?.cancel()
         self.timer = nil
        //do other stuff
    })
}

推荐阅读