基于GCD的登录超时有时会在下次登录尝试时触发

时间:2017-07-31 18:06:14

标签: ios grand-central-dispatch

我在制定问题标题时遇到了一些问题,如果您有更好的选择,请进行编辑。

我有一个登录过程,我添加了一个超时:

private func startTimeout() {
    self.timeoutActive = true
    DispatchQueue.main.asyncAfter(deadline: .now() + 20) { 
        [weak self] in
        guard let weakSelf = self else {
            return
        }

        if weakSelf.timeoutActive && !weakSelf.loggedIn {
            weakSelf.onError("Login timed out")
        }
    }
}

我已经设计了Login过程,以便如果我们因任何原因需要再次登录(例如在注销后,或者在登录过程确定缺少或错误的凭据之后),我们最终会在同一个实例中执行登录的类。

现在,据我所知,我们永远不能阻止执行调度块,只能通过使用一些标志来阻止它,这是我对timeoutActive标志所做的。这就像一个魅力。

但是,如果第二个Login完全定时,以便在新的Login进程启动后执行Previous调度块,则会遇到问题(当启动新的登录过程时,timeoutActive标志再次设置为true) 。新的Login收到一个不正确的超时。

我一直在考虑不同的方法来解决它,并尝试了一些,但无法让它们中的任何一个起作用。

我有一个想法是使用performSelectorAfterDelay而不是GCD,这是可取消的,但在Swift(3)中不可用。

我还想到了一些带有阻止块ID列表的唯一块ID - 但它看起来有些过分。

我也想过将块中的当前调度时间(.now())与原始截止时间(.now()+ 20)进行比较并查看它是否匹配,但我不知道这有多精确截止日期是,感觉不稳定。

我唯一的想法就是在Login过程中创建一些类似于Task的对象,并包含超时并为不同的Logins创建该任务的新实例。看起来像是一些工作,如果我找到一种更简单的方法,我更愿意。

之前是否有人遇到过此类情况并有解决方案?

1 个答案:

答案 0 :(得分:0)

所以这就是我对Dan对该问题的评论所做的:

HAL_TIM_Base_Start(&htim7);
HAL_DAC_Start(&hdac1,DAC_CHANNEL_2);
HAL_DAC_Start_DMA(&hdac1, DAC_CHANNEL_2, (uint32_t*)val, 64, DAC_ALIGN_12B_R);

离开ViewController或完成流程时使用private var timeoutBlock: DispatchWorkItem? = nil private func startTimeout() { self.timeoutBlock = DispatchWorkItem(block: { [weak self] in guard let weakSelf = self else { return } if !weakSelf.loggedIn { weakSelf.onError("Login timed out") } }) DispatchQueue.main.asyncAfter(wallDeadline: .now() + 20, execute: self.timeoutBlock!) } 。这按预期工作!