[swift-evolution] Should explicit `self.` be required when providing method as closure?

Karl Wagner razielim at gmail.com
Mon Mar 6 01:40:59 CST 2017

> On 3 Mar 2017, at 22:14, Alex Johnson via swift-evolution <swift-evolution at swift.org> wrote:
> Hi list members,
> During code review today, I noticed a really subtle memory leak that looked like:
>     self.relatedObject = RelatedObject(callback: relatedObjectDidFinish)
> Where `relatedObject` is a strong reference, `callback` is an escaping closure, and `relatedObjectDidFinish` is a method of `self`. From a memory management perspective, this code is equivalent to:
>     self.relatedObject = RelatedObject(callback: { self.relatedObjectDidFinish })
> In the second example, an explicit `self.` is required. It’s my understanding that this is to highlight that the closure keeps a strong reference to `self`. But, when passing a method, there is no such requirement, which makes it easier to accidentally create a retain cycle.
> This made me wonder if an explicit `self.` should be required when passing a method as an escaping closure. And whether that would help in the same way that the explicit `self.` *inside* the closure is intended to.
> If it were required, the code in the first example would be:
>     self.relatedObject = RelatedObject(callback: self.relatedObjectDidFinish)
> What do you think?
> Alex Johnson
> ajohnson at walmartlabs.com <mailto:ajohnson at walmartlabs.com>
> ajohnson on Slack
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
> https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>


If you wrote it with a trailing closure, you would need to use ‘self’, so I think it’s reasonable to require it when passing the function as an escaping closure as well:

self.relatedObject = RelatedObject { self.relatedObjectDidFinish() } // self required here

Similarly, it would be nice if we had this convenient syntax for unowned function references:

self.relatedObject = RelatedObject { [unowned self] in self.relatedObjectDidFinish() }

would become:

self.relatedObject = RelatedObject(callback: (unowned self).relatedObjectDidFinish)

- Karl
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170306/d84360c1/attachment.html>

More information about the swift-evolution mailing list