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?
2 Answers 2
@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.
5 Comments
DataSource instance doesn't live past the end of callDataSource, as stated in the question.uberManager.getPrice { [success] but you didn't so the compiler captured the variable for you automatically.DataSourceThe 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
DataSourceinstance that created it.