简体   繁体   中英

How to quit “DispatchQueue.main.asyncAfter” in Swift

I want to quit "DispatchQueue.main.asyncAfter" when deinit is called.

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
        //...
    }
}

When ViewController do _ = self.navigationController?.popViewController(animated: true) and deinit is called, deinit in ViewController and subView is called at first and after a few minutes doSomething() is called. I want to stop doSomething() when popViewController is executed. How can I do it?

You could schedule a Timer with this code block

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

hold on to the timer and cancel it before popViewController like this:

timer.invalidate()

Notice the [weak self] and the self?.domeSomething() which I put there to avoid the hard reference to the viewcontroller and read Laffen's more detailed answer on this.

In Swift we have something called ARC( Automatic Reference Counting ). ARC will make sure any object with at least one strong reference to it, will not be removed from memory.

In your case you're creating a strong reference to self in the closure of the async task created by DispatchQueue.main.asyncAfter .

You need to tell the compiler that this reference is either weak or unowned (See attached link for more info.), this will enable the instance of self to be deinitialised even though you have a reference to self from the closure.

The weak keyword can be used in cases where you want the closure to run and make actions that doesn't require a reference to self . This is helpful to use if you don't know if self is alive or not.

The unowned keyword can be used in cases where you don't need the closure to run without a reference to self . This must be used in cases where you know self self is still alive.

Getting a weak or unowned reference of self in the closure can be achieved like in the example below:

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

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

It's worth mentioning that if you're not using a deadline, but calling .async { ... } directly does not result in capturing self and therefore can be used safely without defining weak/unowned self .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM