[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