[swift-evolution] A shortcut for weakly referencing functions
Radosław Pietruszewski
radexpl at gmail.com
Fri Apr 1 11:26:27 CDT 2016
>> Here’s a pattern I find myself doing quite often:
>>
>> 1> class Child {
>> 2. var onSomeEvent: () -> Void = { }
>> 3. }
>> 4> class Parent {
>> 5. let child = Child()
>> 6. init() {
>> 7. child.onSomeEvent = doSomething
>> 8. }
>> 9. func doSomething() {
>> 10. }
>> 11. }
>>
>> I have some ownership hierarchy of classes (often controllers — view
>> controllers — views), where I pass information from children up to
>> parents using closures set by the parent.
>>
>> I like this pattern because children classes don’t have to be tied to
>> knowledge about their parents, and I don’t have to define delegate
>> protocols. It’s very clean, and also very easy to set up.
>>
>> The only problem is that there’s a strong danger of introducing reference
>> cycles.
>>
>> With class properties, you can quite easily see the potential for a
>> reference cycle and mark references to parents with weak/unowned. And
>> with `self` captures in closures, you’re reminded of memory management by
>> having to be explicit about `self`. But when passing references from
>> parents to children, there’s no way to mark the closure property as
>> `weak` (and there’s no reminder of the danger).
>
> I will go ahead and note, at least in terms of writing the proposal, I
> don't find this argument very strong. The proposed syntax still requires
> you to know about the cycles involved.
Oh, I agree. The proposal doesn’t fix the relative undiscoverability (is that a word?) of the potential for reference cycles when passing function references.
Still — I think, maybe, when you can say in tutorials and programming guides that you avoid reference cycles when passing functions down the ownership hierarchy by wrapping those function references in #weak(…) / #unowned(…), it might be easier to grasp and remember than `{ [unowned self] in self.foo($0) }`.
>
>>
>> * * *
>>
>> Right now, every time I pass a closure down to children, I have to wrap
>> my references like so:
>>
>> { [unowned self] self.doSomething($0) }
>>
>> instead of a neat and simple function reference:
>>
>> doSomething
>>
>> I think it would be useful to have a shortcut syntax for creating weak
>> and unowned references to functions, like so:
>>
>> @unowned(doSomething)
>>
>> or perhaps:
>>
>> #unowned(self.doSomething)
>>
>> * * *
>
> I really like the #unowned syntax! It's expressive and in line with
> other pieces of Swift sugar. Would +1 if it came to a proposal!
>
> The @ version doesn't make as much sense as it's not an attribute.
Thank you. You’re probably right about #unowned(…) vs @unowned(…). I thought of at-syntax because it feels like applying an attribute to the function reference. (IIRC, weak and unowned were @weak and @unowned in Swift β1)
>
>>
>> An alternative would be the ability to mark closure properties as weak or
>> unowned. Then I could, at the *child* level, say:
>>
>> unowned let onSomeEvent: () -> Void
>
> I don't particularly think it makes sense, because it is prescriptive.
> If some other user in your codebase wanted the cycle, they couldn't get
> it. Plus, what would it mean when the closure isn't capturing anything?
Rright. Because it’s not really about assigning literal closures to such a parameter, rather assigning method references, where the method’s receiver (self in my example) is implicitly captured… So it seems like it should be a responsibility of the code assigning the reference.
— Radek
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160401/7e3fd70a/attachment.html>
More information about the swift-evolution
mailing list