No more [weak self], or the weird new future of delegation

Ready for some property wrappers?

It’s been almost three years since I wrote ”Do you often forget [weak self]? Here’s a solution”, which luckily resonated with many people. I’ll do a short recap, but if you want a deeper understanding of the topic you can go ahead and read that article first.

In short, the problem I was trying to solve was this: since traditional “protocol-based” delegation was seen by many (including me) as too cumbersome, alternative “closure-based” delegation was gaining traction. The concept is easy and, in pseudo-UIKit-code, looks something like this:

This is neat and easy, but also very very tricky: see how we just introduced a retain cycle? ViewController holds a strong reference to TextField, and the TextField’s didUpdate now holds a strong reference to a ViewController. Which is why it’s always necessary in these cases to use [weak self]:

This is, of course, extremely easy to miss or forget, and the next moment you’re spending 40+ minutes trying to debug your memory leak.

My solution was to shift the responsibility to include [weak self] from the API user (ViewController), to the API designer (TextField), using this structure:

(read the original article for more details)

And the code now looks like this:

So now didUpdate itself makes sure that no unwanted retain cycles are introduced, which is just what we wanted.

And that was pretty much it.

It was a neat little trick, and generated a good amount of positive feedback, as well as some very fair debate over the stylistic choice, especially the shadowing of self.

I myself adopted the patter in all my side-projects, but didn’t really expect anyone else to jump onboard. Arguably, using the Delegated<Int> instead of (Int) -> Void was a hard sell. It looked weird and unintuitive.

So here comes today. And I’m back with an even weirder solution. Let me present to you: Delegated 2.0.

…yeah, now a property wrapper.

So what changed? Let’s go back to our snippet and update it with the new shiny Delegated property wrapper:

And okay, if you’re rolling your eyes right now, I hear you. This seems somewhat ridiculous. But also… beautiful? Just see how natural this looks. This is so, so similar to the original “closure-based” delegation with all its simplicity, but now also with the additional benefit of safety.

You can make up your own mind about whether you like it or hate it (and please let me know in the comments!). I’ve been using this for a few months (including in both Ask Yourself Everyday app & Time and Again) and I am loving it. It’s a huge productivity booster (the boilerplate of writing protocol-based delegation is just too much), and with this I don’t need to think about [weak self] ever, which is lovely.

With Swift generics being somewhat limited, there are still of course some drawbacks to this solution. First and foremost — only closures that have exactly one argument and no return value can be marked as @Delegated. Which means that this will not compile:

But this will:

Which honestly makes me sad. It’s one of my biggest pet peeves with Swift.

Alternative (although not much prettier) solution is to create additional property wrappers for different number of arguments. For example, Delegated0:

After creating a few of these, you’ll have this:

Don’t blame me, blame Swift.

It’s not necessary (you can just write it yourself), but if anything, the new @Delegated property wrapper is available as a Swift package. It includes base @Delegated as well as @Delegated0@Delegated4, which you might or might not need. Check it out:

Thanks for reading the post! Don’t hesitate to ask or suggest anything in the “responses” section below. You can also contact me on Twitter or find me on GitHub. If you have written a piece (or stumbled upon one) exploring similar topic — make sure to post a link to it in the responses so I can include it right below.

Hi! If you want to support me, please check out my apps: “Ask Yourself Everyday”,“Time and Again” and “Women’s Football 2017”. For business inquiries, reach me at oleg@dreyman.dev. Thanks for reading!

iOS development know-it-all, Co-founder at nicephoton.com. Talk to me about Swift, coffee, photography & motorsports.