6

I have the following code defined in a view controller.

    _ = accountService.getAccount()

      .then { user -> Void in

         self.txtBxUser.text = user.username
         self.txtBxEmail.text = user.email
   }

getAccount makes a REST API request.

If the user dismisses the view controller before the call has returned, what happens to the call back chain? Does it still run given that, I presume, it's still referenced?

Ian Warburton
  • 15,170
  • 23
  • 107
  • 189

2 Answers2

2

Should I be concerned about retain cycles? tl;dr: it’s safe to use self in promise handlers.

This is safe:

somePromise.then {
    self.doSomething()
}

Provided somePromise resolves, the function passed to then will be released, thus specifying [weak self] is not necessary.

Specifying [unowned self] is likely dangerous.

You’re telling me not to worry about retain cycles?! No, it’s just that by default you are not going to cause retain cycles when using PromiseKit. But it is still possible, for example:

self.handler = {
    self.doSomething
    self.doSomethingElse }
somePromise.then(execute: self.handler)

The closure we assign to handler strongly retains self. handler is strongly retained by self. It’s a typical retain cycle. Don’t write typical retain cycles!

Notably, this is not a retain cycle:

 somePromise.then(execute: self.doSomething).then(execute: self.doSomethingElse)

source

JuicyFruit
  • 2,638
  • 2
  • 18
  • 35
2

If the user dismisses the view controller before the call has returned, what happens to the call back chain? Does it still run given that, I presume, it's still referenced?

Yes, it does still run.

Be forewarned that the reference to self in the closure means that it is also keeping a reference to the view controller until that then closure finishes running. For that reason, if there's a chance the view controller could have been dismissed, you might want to use a weak reference:

_ = accountService.getAccount().then { [weak self] user -> Void in
    self?.txtBxUser.text = user.username
    self?.txtBxEmail.text = user.email
}

Ideally, you should also make getAccount cancellable and cancel it in the view controller's deinit.

(Note, in FAQ - Should I be Concerned About Retain Cycles, the PromiseKit documentation points out that you don't need weak references, which is correct. It's just a question of whether or not you mind if the deallocation of the dismissed view controller is deferred until after the promise is fulfilled.)

Rob
  • 415,655
  • 72
  • 787
  • 1,044