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

K.K*_*K.D 2 xcode ios swift

我想在调用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
        //...
    }
}
Run Code Online (Sandbox Code Playgroud)

_ = self.navigationController?.popViewController(animated: true)调用ViewController do 和deinit时,首先在ViewController和subView中调用deinit,然后在几分钟后doSomething()调用。我想在doSomething()执行popViewController时停止。我该怎么做?

Laf*_*fen 7

在Swift中,我们有一个叫做ARC(自动引用计数)的东西。ARC将确保不会从内存中删除至少具有一个强引用的任何对象。

在您的情况下,您将self在结束由创建的异步任务时创建强烈引用DispatchQueue.main.asyncAfter

您需要告诉编译器此引用为weakor或unowned(请参阅附件链接以获取更多信息。),self即使您self从闭包中引用了它,也可以取消初始化的实例。

weak关键字可以在你想关闭运行的情况下,使操作使用,不需要为参考self

unowned如果您不希望闭包在不引用的情况下运行闭包,则可以使用该关键字self

可以在闭包中获取self weakunowned引用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()
}
Run Code Online (Sandbox Code Playgroud)

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


nos*_*joe 7

您可以Timer使用此代码块安排

let timer = Timer.scheduledTimer(withTimeInterval: 5.0, repeats: false) { [weak self] timer in
    self?.doSomething()
}
Run Code Online (Sandbox Code Playgroud)

按住计时器并在取消之前将其取消,popViewController如下所示:

timer.invalidate()
Run Code Online (Sandbox Code Playgroud)

请注意,我[weak self]self?.domeSomething()此处放置了和,以避免对视图控制器进行硬引用,并阅读Laffen对此的更详细的答案。