Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does passing a function belonging to self cause a retain cycle when not in a closure?

If you need to reference self inside of a closure, it's good practice to pass it in as weak or unowned to prevent a retain cycle.

If I pass the function that belongs to self directly, will it cause a retain cycle? Or does it need to be nested inside a closure to weakify self?

Passing directly

UIView.animateWithDuration(0.3,
        delay: 0.0,
        usingSpringWithDamping: 0.7,
        initialSpringVelocity: 0.1,
        options: .CurveEaseOut,
        animations: self.view.layoutIfNeeded, // does this cause retain cycle? 
        completion: nil)

Wrapping in a closure

UIView.animateWithDuration(0.3,
        delay: 0.0,
        usingSpringWithDamping: 0.7,
        initialSpringVelocity: 0.1,
        options: .CurveEaseOut,
        animations: { [unowned self] in
            self.view.layoutIfNeeded()
        },
        completion: nil)
like image 389
Chris Avatar asked Dec 07 '15 15:12

Chris


People also ask

How can you avoid a strong reference cycle in a closure?

A strong reference cycle happens when 2 instances keep a strong reference to each other. You can accidentally create such a cyclic reference, for example when working with 2-way “links” between objects, or with closures. You can break the cycle by marking a reference as weak, or by setting one of the references to nil.

Why use weak self in closure?

In Swift, [weak self] prevents closures from causing memory leaks in your application. This is because when you use [weak self], you tell the compiler to create a weak reference to self. In other words, the ARC can release self from memory when necessary.

How do you retain retaining cycle?

In order to prevent this retain cycle, we need to declare at least one of the variable as weak or unowned. We can break the retain cycle with adding a weak keyword before either the driver property of the Car class or the car property of the Person class.

What is the difference between weak self and unowned self?

Use a weak reference whenever it is valid for that reference to become nil at some point during its lifetime. Conversely, use an unowned reference when you know that the reference will never be nil once it has been set during initialization. In general, be very careful when using unowned.


1 Answers

This should not create a reference cycle, but even if it did that would be ok. The reference cycle would only exist until the animation completed, at which point it would be broken. Creating short-lived reference cycles can actually be beneficial because it ensures that the target continues to exist for the life of the call. Cycles are not inherently a problem. Unbreakable cycles are the problem.

There are two reasons that this doesn't create a cycle. First, there is no "cycle." The system is going to reference something (more on that in a second), sure. But where's the reference to "the thing that is referencing that something?" To say it a bit more clearly, even if the animation system referenced self, how is self referencing the animation system? There is no cycle.

The other reason there is no cycle is that you're not passing self to animation system anyway. Your passing self.view.layoutIfNeeded. In Swift, that's equivalent to:

UIView.layoutIfNeeded(self.view)

You're not passing self here. You're passing a view. Now the animation system almost certainly will hold a reference to that view until the animation completes, but that's fine. That's still not a cycle.

like image 103
Rob Napier Avatar answered Sep 21 '22 03:09

Rob Napier