user172902 user172902 - 2 months ago 16
Swift Question

weak Delegate and class protocol

I have been using protocol and delegate method to pass data back to the previous VC after dismissViewControll is called. Below is how I would normally do it as it is not way that most tutorial was written

protocol someVCDelegate {
func somefunction()
}

var delegate: someVCDelegate!


However, I came across this class/weak approach of writing it.

protocol someVCDelegate : class {
func somefunction()
}

weak var delegate: someVCDelegate!


I understand that weak is associated to ARC and avoiding retain cycle. However, I am not sure when I would need it as in all my cases, not doing weak delegate works find (VC does deinit). In what sort of situation would I need weak delegate? Also, why is it "!" after weak, normally it is "?" after weak right?

Rob Rob
Answer

You say:

However, I am not sure when I would need it as in all my cases, not doing weak delegate works

You only need the weak protocol-delegate pattern when you have a potential for a strong reference cycle, i.e. a circular series of strong references. For example, consider:

  • an object (the "parent") that has a property (the "child"), i.e. the parent has a strong reference to the child;

  • the child has a delegate property; and

  • you set the child's delegate to refer to the parent object.

In that case, it's critical that the delegate be weak reference or else you'll have a strong reference cycle.

Note, this is a trivial example and sometimes the chain of strong references can be rather complicated. For example, consider a UIView subclass that has a delegate property. The potential strong reference cycle can be quite long, from the view controller to its root view, through a series of subviews of subviews, all the way down to the UIView with the delegate that might potentially reference back to the view controller. That will result in a strong reference cycle, too, and we'd be inclined to use a weak reference for that delegate for that reason.

But when you employ protocol-delegate pattern for passing data between view controllers, though, this generally isn't a problem (with the exception of view controller containment) because the presenting view controller doesn't own the presented view controller. The view controller hierarchy generally maintains the strong references to the view controllers. So, when you dismiss the presented view controller, it is deallocated and the potential strong reference cycle is resolved.

Often, we'll instinctually employ the weak protocol-delegate pattern (simply because it prevents strong reference cycles from occurring at all). But sometimes you will use strong references. The most common strong reference pattern is NSURLSession whose delegate is a strong reference. As the documentation for init(configuration:delegate:delegateQueue:) warns us:

The session object keeps a strong reference to the delegate until your app exits or explicitly invalidates the session. If you do not invalidate the session by calling the invalidateAndCancel() or finishTasksAndInvalidate() method, your app leaks memory until it exits.

While this might seem paradoxical, the advantage of this strong reference pattern is that the session knows that it can safely call its delegate methods without fear of the object having been deallocated. (As an aside, this strong delegate behavior of NSURLSession rarely rears its ugly head, because we often use the completion handler methods and don't employ the delegate methods at all, and when we do employ delegate methods, we often have some object other than a view controller as the delegate for the session.)

In short, you really have to evaluate each situation and determine whether the weak reference that we instinctually lean towards is better, or whether you have one of those cases where your protocol is better served with strong references.