3
votes

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?

2
do you at any point make the delegate nil? or does the previous VC not keep a reference to the next VC? im skeptical as to why the deinit is being called on either VC, if an object has at least one strong reference to it, ARC wont clean it up. So if the previous VC has a reference to the next VC and the next VC has a (strong) delegate reference to the previous, ARC wont delete them if they lose all other references causing a memory leakFonix
its always good practise to make the delegate weak anyway, its not difficult and can save you some headaches in the future. can be difficult to debug if it does become an issue laterFonix
Just read this today. It clarified a few loose ends re: ARC for me. raywenderlich.com/134411/arc-memory-management-swiftAdrian

2 Answers

3
votes

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.

0
votes

Why it's weak: A weak reference is a reference that does not keep a strong hold on the instance it refers to, and so does not stop ARC from disposing of the referenced instance. This behavior prevents the reference from becoming part of a strong reference cycle. Or simply, You resolve strong reference cycles by defining some of the relationships between classes as weak or unowned references instead of as strong references.

And it's "!" after weak because it's implicitly unwrapped. It's gonna have a value.

Sometimes it is clear from a program’s structure that an optional will always have a value, after that value is first set. In these cases, it is useful to remove the need to check and unwrap the optional’s value every time it is accessed, because it can be safely assumed to have a value all of the time.