Swift: Can weak reference be deallocated during optional binding?

1.6k views Asked by At

Lets examine the following example

SomeLib.someAsyncFunction { [weak someVariable] in
   if let someVariableU = someVariable {
      // now someVariableU is unwrapped and strong reference created , we can use it as regular
   }
}

I assume that optional binding has a low level implementation similar(not exactly of course) to something like this

if variable != nil {
   return variable!
}

So, my question - is it possible that the object referenced by weak reference will deallocated during optional binding, I mean the last strong reference to the object is "cleared". If so what will happen in this case?

What will happen if the "nil check will pass" and then it will be deallocated, what will happen to "force unwrap"(I used parentheses because I understand that it's not exactly how it works)!

So, can somebody explain if this situation is even possible, and is o than what will happen?

2

There are 2 answers

8
matt On BEST ANSWER

This entire structure, which dates back way into the Objective-C days, is traditionally called the "weak–strong dance". Let me explain the purpose of the dance.

Our overall purpose is: avoid the danger of a retain cycle and memory leak. That is why we say weak somevariable.

Having done that, however, we do indeed introduce the danger that the object pointed to by somevariable might be deallocated. However, we deal coherently with that danger, by saying if let. Here's how:

  • The object might have been deallocated by the time we enter the first curly braces in your code. But that's not a problem. The if let means that if the object has been deallocated, then in that case we get nil and we do nothing (we never enter the second curly braces).

  • If the object has not been deallocated by the first curly braces, then the if let succeeds, and then, as Cristik says, the if let creates a strong reference and now we enter the second curly braces with a guarantee that the object will persist for their entirety.

Thus, we get coherent and consistent behavior.

SomeLib.someAsyncFunction { // someVariable might be deallocated...
   [weak someVariable] in // ...and that is the point of `weak`, to allow that
   if let someVariableU = someVariable { // find out whether someVariable was deallocated
      // if we get here, someVariable was _not_ deallocated...
      // and someVariableU is a strong reference and persists thru this block
   }
}
0
Cristik On

No, the object won't be deallocated during the execution of the optional binding block.

if let someVariableU = someVariable creates a strong reference, thus as long as that strong reference will be alive, so will the object it points to.