I have a view controller like this:
class PublicationListViewController: UIViewController {
var publicationQuery: (() -> [Publication])!
func initWith(title: String, publicationQuery: () -> [Publication]) {
self.title = title
self.publicationQuery = publicationQuery
}
}
Why am I getting a "Assigning non-escaping parameter 'publicationQuery' to an @escaping closure" error?
Escaping Closures
Because by storing the publicationQuery
into a property you are allowing it to "escape" from the initializer (it lives even after the initiliazer finished its execution, thus is a potential cause of retain cycle). To be able to do that you have to explicitly mark it as escaping using @escaping
annotation:
class PublicationListViewController: UIViewController {
var publicationQuery: (() -> [String])!
// notice that now publicationQuery uses @escaping annotation
func initWith(title: String, publicationQuery: @escaping () -> [String]) {
self.title = title
self.publicationQuery = publicationQuery
}
}
Read more about escaping in Escaping Closures section of the Closures documentation.
Preventing Retain Cycle
When using escaping closures, you have to be careful not to create a retain cycle. Easiest way is to use the capture list when creating escaping closure, and in that capture list you explicitly capture self
as a weak
reference:
// use [weak self] capture list to make sure that you don't create another strong reference to self
pubController.initWith(title: "Title") { [weak self] () -> [String] in
// use guard to safely unwrap the self
guard let `self` = self else { return }
// here self will be non-optional value that you can directly use
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With