[swift-evolution] Proposal: weakStrong self in completion handler closures

Jacob Bandes-Storch jtbandes at gmail.com
Sat Dec 5 15:36:28 CST 2015


When you use "weak self", self becomes Optional inside the closure, and
indeed it *can* become nil partway through. This is the same as __weak in
Objective-C, and there's actually a clang warning for it (search for
"repeated-use-of-weak" or see
http://devstreaming.apple.com/videos/wwdc/2013/404xbx2xvp1eaaqonr8zokm/404/404.pdf
).

That's why "guard let strongSelf = self" is important, and I think "guard
let self = self" would add value without adding confusion.

The current behavior is easily demonstrated:

import Foundation

class C {
    func doStuff() {
        dispatch_async(dispatch_get_global_queue(0, 0)) { [weak self] in
            print("self is \(self), waiting...")
            usleep(500_000)
            print("self is \(self), waiting...")
            usleep(500_000)
            print("self is \(self)")
        }
    }
}

var obj: C? = C()
obj!.doStuff()

usleep(750_000)
print("main thread - releasing")
obj = nil

sleep(2)



On Sat, Dec 5, 2015 at 1:24 PM, Javier Soto <javier.api at gmail.com> wrote:

> My understanding was that [weak variable] behaved that way in Swift
> already (but now I'm not certain and can't find a definitive answer on the
> book), creating a strong reference. Otherwise this turns into inconsistent
> behavior, where the variable could deallocate and become nil at any point
> inside the closure.
>
> Those semantics are also important in a case with a closure within a
> closure:
>
> function1(){ [weak self] in
> function2() {
> // the value (If present) inside Optional<Self> is a strong reference here
> }
> }
> On Sat, Dec 5, 2015 at 11:22 AM Jacob Bandes-Storch via swift-evolution <
> swift-evolution at swift.org> wrote:
>
>> Another approach would be to simply allow
>>
>> guard let self = self else { return }
>> On Sat, Dec 5, 2015 at 3:48 AM Robert Vojta <rvojta at me.com> wrote:
>>
>>> Hi all,
>>>
>>> let’s say we have a completion handler closure for some function
>>> (networking, …) and we have [weak self] there. Example …
>>>
>>> doSomething() { [weak self] result in
>>>>>> }
>>>
>>> … then we can use self?.whatever to access self properties, methods. Or
>>> we can try to check if self exists ...
>>>
>>> guard let strongSelf = self else { return }
>>>
>>> … and use strongSelf.
>>>
>>> Can we introduce [weakStrong self] with following behavior:
>>>
>>>  - self is a weak reference
>>>  - when the closure is going to be executed, all weakStrong weak
>>> references are checked if they do exist
>>>  - if they do exist, they’re strong referenced for the closure and the
>>> closure is executed
>>>  - if they don’t exist, closure is not executed
>>>
>>> doSomething() { [weakStrong self] result in
>>>   // Closure code is not executed if self no longer exists
>>>   // self is a strong reference now
>>> }
>>>
>>> What do you think? Does it make sense?
>>>
>>> My motivation is to get rid off of the repetitive code like this one:
>>>
>>> doSomething() { [weak self] result in
>>>   guard let strongSelf = self else { return }
>>>   strongSelf.doSomethingWithResult(result)
>>> }
>>>
>>> Robert
>>> _______________________________________________
>>> swift-evolution mailing list
>>> swift-evolution at swift.org
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
> --
> Javier Soto
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20151205/ae0b1418/attachment.html>


More information about the swift-evolution mailing list