I'm working with network request classes and I'm concerned about crashes. For instance, working with closures is really easy as you pass a callback method to a function:
// some network client
func executeHttpRequest(#callback: (success: Bool) -> Void) {
// http request
callback(true)
}
// View Controller
func reload() {
networkClient.executeHttpRequest() { (success) -> Void in
self.myLabel.text = "it succeeded" // NOTE THIS CALL
}
}
However, since the process that should execute the callback is async, when callbacks interact with container class element (in this case an UIKit
class) it may be vulnerable to crashes in situations like
- The user navigated to another View Controller while the async task was still executing
- The user pressed the home button while the async task was still executing
- Etc...
So, when the callback finally gets fired, self.myLabel.text
might result in a crash, as the View Controller to whom self
was refering could already be deallocated.
Up to this point. Am I right or do swift implement something internally so that this never happens?
If I am right, then here's when the delegate pattern comes in handy, as delegate variables are weak references
, which means, they are not kept in memory if deallocated.
// some network client
// NOTE this variable is an OPTIONAL and it's also a WEAK REFERENCE
weak var delegate: NetworkClientDelegate?
func executeHttpRequest() {
// http request
if let delegate = self.delegate {
delegate.callback(success: true)
}
}
Note how self.delegate
, since it is a weak reference
, it will point to nil
if the View Controller (who implements the NetworkClientDelegate
protocol) gets deallocated, and the callback is not called in that case.
My question would be: do closures have anything special that makes them a good choice in scenarios similar to this one, rather than going back to delegate pattern? It would be good if examples of closures (that won't end up in crashes due to nil pointer) are provided. Thanks.