我整理了以下结构,以在网络连接速度慢时提醒用户。
当函数要调用服务器时,它会创建一个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秒延迟完成之前响应返回的情况下,通知仍会触发。我在这里做错了什么???是否有更好的模式可用于此类情况?
谢谢您的帮助!
最佳答案
Timer
是执行此操作的更好方法(为什么在收到响应并且知道不再需要该任务后,将已分派的任务保留在此处)。但是我看不到上面会导致您描述的行为的任何东西。我建议您在isOn
上添加一些明智的日志记录和/或“监视”功能,以便您可以看到它的设置/重置位置。
但是Timer
实现可能看起来像:
class ResponseTimer {
private weak var timer: Timer?
func schedule() {
timer = Timer.scheduledTimer(withTimeInterval: 8, repeats: false) { _ in // if you reference `self` in this block, make sure to include `[weak self]` capture list, too
NotificationCenter.default.post(...)
}
}
func invalidate() {
timer?.invalidate()
}
// you might want to make sure you `invalidate` this when it’s deallocated just in
// case you accidentally had path of execution that failed to call `invalidate`.
deinit {
invalidate()
}
}
然后您可以执行以下操作:
func getSomethingFromFirebase() {
var responseTimer = ResponseTimer()
responseTimer.schedule()
ref.observeSingleEvent(of: .value) { snapshot in
responseTimer.invalidate()
//do other stuff
}
}