Eugene Gordin
Eugene Gordin

Reputation: 4107

How can you stop/cancel callback in Swift3?

In my app I have a method that makes cloud calls. It has a completion handler. At some point I have a situation when a users makes this call to the cloud and while waiting for the completion, the user might hit log out.

This will remove the controller from the stack, so the completion block will be returned to the controller that is no longer on a stack.

This causes a crash since I do some UI tasks on that completion return. I did a workaround where, I'm not doing anything with the UI is the controller in no longer on a stack.

However, I'm curious if it's possible to cancel/stop all pending callbacks somehow on logout?

Upvotes: 2

Views: 1703

Answers (2)

Nikita Leonov
Nikita Leonov

Reputation: 5694

For the granular control over operations' cancellation, you can return a cancellation token out from your function. Call it upon a need to cancel an operation.

Here is an example how it can be achieved:

typealias CancellationToken = () -> Void

func performWithDelay(callback: @escaping () -> Void) -> CancellationToken {
    var cancelled = false
    // For the sake of example delayed async execution 
    // used to emulate callback behavior.
    DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
        if !cancelled {
            callback()
        }
    }
    return { cancelled = true }
}

let cancellationToken = performWithDelay {
    print("test")
}

cancellationToken()

For the cases where you just need to ensure that within a block execution there are still all necessary prerequisites and conditions met you can use guard:

  { [weak self] in 
    guard let `self` = self else { return }
    // Your code here... You can write a code down there 
    // without worrying about unwrapping self or 
    // creating retain cycles.
  }

Upvotes: 1

mfaani
mfaani

Reputation: 36317

I'm not sure, but I think something is tightly coupled. Try doing:

{ [weak self] () -> Void in
            guard let _ = self else { return }
//rest of your code
}

If you get deinitialized then your completioHanlder would just not proceed.

Upvotes: 3

Related Questions