6

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)
Chris
  • 7,270
  • 19
  • 66
  • 110

2 Answers2

3

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.

Rob Napier
  • 286,113
  • 34
  • 456
  • 610
1

There is no reference cycle since self doesn't capture the closure but if you don't want that there is another strong reference to self you can use the wrapping closure.

If you are sure that self is not deallocated in the next 0.3 seconds you can use unowned otherwise weak. (I would use weak just to be sure it doesn't crash)

Qbyte
  • 12,753
  • 4
  • 41
  • 57