I fell into this trap and had a retain cycle.

So if you have ever written code like foo.runOnCompletion(myHandler), where myHandler is your own instance method, then you will have a memory issue when foo object retains the closure.

Let’s jump straight to fixing it first, which is:

foo.runOnCompletion { [weak self] in

Tada! weak self to the rescue.

That is the usual way to writing a closure. And Swift language has been nice 🫶🏻 to force us to remind ourselves whenever self will be retained. Tough love to speak.

ie. If you omit capturing self as weak or unowned, which would imply strong capturing, then you are forced to use self every time within the closure –> remind us self is being strongly retained.

What’s the pitfall then?

Going back to foo.runOnCompletion(myHandler).. I was not forced to write self.myHandler, so I was led to thinking that there is no retain cycle on self.

As you now know, that is incorrect.

The topic was also discussed in Swift Forum.

Hopefully Swift will improve, providing a way to pass a func weakly.

I am sure everyone is sick of writing tons of publisher.sink { [weak self] in ... }




Back to Home