如何在Swift中退出“DispatchQueue.main.asyncAfter”

11

当调用deinit时,我希望退出"DispatchQueue.main.asyncAfter"。

subView.swift

DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
    self.doSomething()
}

func doSomething(){ 
    if self.subView.flgA == false { //error because subView's deinit is already called
        //...
    }
}

当 ViewController 执行 _ = self.navigationController?.popViewController(animated: true) 时,会首先调用 ViewController 和 subView 的 deinit,几分钟后才会调用 doSomething()

我想在执行 popViewController 时停止 doSomething(),我该如何做?

2个回答

15
您可以使用以下代码块来安排一个计时器:Timer
let timer = Timer.scheduledTimer(withTimeInterval: 5.0, repeats: false) { [weak self] timer in
    self?.doSomething()
}

popViewController之前,将计时器保持并取消,像这样:

timer.invalidate()

请注意我添加的[weak self]self?.domeSomething(),以避免对视图控制器的强引用,并阅读Laffen更详细的答案。


我不知道我可以像你的代码一样使用Timer和[weak self]来编写它。谢谢! - K.K.D

12
在Swift中,我们有一种称为ARC(自动引用计数)的东西。ARC将确保具有至少一个强引用的对象不会从内存中删除。 在你的情况下,你正在创建一个对由DispatchQueue.main.asyncAfter创建的异步任务的闭包中的self的强引用。 你需要告诉编译器,这个引用是弱引用或无主引用(请参阅附带链接以了解更多信息),这将使self的实例被销毁,即使你从闭包中引用了self。 在不需要对self引用进行操作的情况下,可以使用weak关键字。如果你不知道self是否仍然存在,使用它很有帮助。 在不需要对self引用进行操作的情况下,可以使用unowned关键字。必须在你知道self仍然存在的情况下使用它。 在闭包中获取self的弱引用或无主引用可以像下面的示例一样实现:
DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
    [weak self] in
    self?.doSomething()
}

DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
    [unowned self] in
    self.doSomething()
}

值得一提的是,如果您没有使用截止日期,但直接调用.async { ... }不会捕获self,因此可以安全地使用而无需定义weak/unowned self

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接