Finding nil after a nil check... | DispatchQueue.main.async

I’ve found a somewhat silly bug. I was curious if anybody could help understand what’s going on.

Imagine my surprise when I stumbled upon this:

One can clearly see there’s a nil check on chartedData, yet it still finds nil.

Putting everything on the main thread solves the bug:

DispatchQueue.main.async {
      if chartedData != nil {
                cursorIndex = chartedData!.count - 1 // does not crash
      }
 }

Interesting…

Anyone has any ideas as to what goes on under the hood there ?

In any case, I’m officially twice as paranoid about unwrapping optionals now haha

It means that there is a change to that variable chartedData occurring after the DispatchQueue has been initiated. DispatchQueue.main.async { runs concurrently with other code that is executing so it’s likely that by the time the code in DispatchQueue.main.async closure is executed chartedData has been set to nil.

1 Like

Huh. I guess that makes sense?

With that in mind I found a line earlier in the func where chartedData can sometimes be set to nil. My code was a bit messy and I missed it :sweat_smile:

Just in case someone stumbles upon this problem and takes interest, it essentially looked like this:

[... stuff]

DispatchQueue.main.async {
   chartedData = somethingThatCanSometimesBeNil
}

[... stuff]

if chartedData != nil {
   DispatchQueue.main.async {
          cursorIndex = chartedData!.count - 1 // can crash
   }
}

I’ll be more careful about this. Thanks a lot Chris!

No problem Raphael.

A better way to write this and use optional is by using a guard statement instead

guard let chartData else {
   return
}

// now you can use chartData without force unwrapping it