1

Let's say I have a view controller, and in its viewDidLoad I am calling this function:

func callDataSource()
{
 let dataSource = DataSource()
 dataSource.callUber {
 print("In viewDidLoad")
 }
 return
}

and this DataSource class is

class DataSource {
 func callUber(withSuccess success: @escaping (() -> Void))
 {
 let uberManager = UberDataFetcher()
 uberManager.getPrice {
 print("In Data Source")
 success()
 }
 return
 }
}

And this UberDataFetcher is just a class that calls an Uber API. My question is: I have defined the DataSource object within the scope of the callDataSource function; this means that the object gets deallocated once that function returns. How does the completion block outlives the instance that has created it?

asked Mar 18, 2019 at 19:50
2
  • "How does the completion block outlive the instance that has created it?" It's not the DataSource instance that created it. Commented Mar 18, 2019 at 20:05
  • It's not the "DataSource" instance that has created it, but it's associated with the calling of the "DataSource" function Commented Mar 18, 2019 at 20:35

2 Answers 2

0

@escaping marks the closure as possibly outliving the context that created it. A closure is an object that has associated state (ie your capture list) along with a reference tot he function. Your Datasource retains the closure so it stays alive at least as long as the Datasource hangs on to it. Not that this might be a problem if your closure retained self, because then self would also last for at least as long as the closure lasts, which is as long as Datasource holds on to it.

answered Mar 18, 2019 at 19:57
Sign up to request clarification or add additional context in comments.

5 Comments

"it stays alive at least as long as the Datasource hangs on to it" But the DataSource instance doesn't live past the end of callDataSource, as stated in the question.
UberDataFetcher retains it before DataSource dies. ie the retain count goes up by one for every capture.
Where does it do that?
Automagically. you could have written a capture list uberManager.getPrice { [success] but you didn't so the compiler captured the variable for you automatically.
Right, it retains the closure, not the DataSource
0

The closure is an object for purposes of memory management. Referring to it in the UberDataFetcher's callback means that it is retained by that closure. So it is kept alive, along with anything that it captures, until the end of that scope.

let uberManager = UberDataFetcher()
uberManager.getPrice {
 print("In Data Source")
 success() // <--- Captured
} // <--- End of scope
answered Mar 18, 2019 at 20:02

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.