31

Since I upgraded to Xcode 11 and Swift 5.1 I've encountered a strange issue -- after an optional variable is instantiated, it can still show as up nil in the Xcode debugger!

I have an optional class variable called booking:

var booking: Booking?

It's of type Booking:

public struct Booking: Codable {
    var id: Int?
    var start_time: Date?
    var payment_currency: String = "USD"
    var payment_amount: Int?
}

When I'm stepping through the code, I can see booking before it's allocated... It's nil, great:

enter image description here

Then after it's allocated... What, still nil??:

enter image description here

I wondered if it was being treated like a lazy variable somehow. But it's not really nil, because it can be accessed:

enter image description here

After searching for a while, I wondered if my build schema in Xcode didn't have its "Debug executable" flag set. But it does. I even cleaned and rebuilt the project with the flag off and on to be sure.

enter image description here

Whether I view booking in the Variables View or enter p booking in the Console View, it shows up as nil.

What's going on here? I need the predictability of debugging I had before this upgrade.

UPDATE

I distilled a simple way to reproduce the issue. First, create an empty single-view project and add this to the top of AppDelegate.swift:

public struct Booking: Codable {
    var start_time: Date?
    var payment_currency: String = "USD"
}

Then add these lines to the application(_:didFinishLaunchingWithOptions:) func:

booking = Booking()
print("booking.payment_currency = \(booking?.payment_currency ?? "NULL")")

Set a breakpoint as before and when running, notice that the debugger shows booking as nil even after being assigned, as in my original case.

Then comment out the start_time variable, re-run, and notice that now the debugger shows booking having a value after being assigned, as one would expect.

So it seems that Date variables, optional or not, in a struct like this make debugging confusing. Specifically Date variables -- change the variable to other types like Int, Int?, String, String?... and there's no issue.

Unless I'm missing something very basic, this seems like a bug in the Xcode debugger to me. If so, would the best way to report it be at https://developer.apple.com/bug-reporting/?

Dylan
  • 2,015
  • 1
  • 17
  • 28
  • 1
    Can you provide instructions for reproducing this issue? If so it could be a good bug report to Apple. – matt Sep 26 '19 at 02:49
  • I think that's my next step tomorrow, trying to distill it down into a very small project. I'm hoping somebody else has encountered this though, and that there's a simple solution or something else I don't know. – Dylan Sep 26 '19 at 02:57
  • 1
    I can't tell without reproducing, but your description and screen shots just scream "bug" at me. :) – matt Sep 26 '19 at 03:02
  • Have you tried the usual go-to trouble shooting steps? In order of increasing nuisance: restarting Xcode, clean build, clearing derived data. – Alexander Sep 26 '19 at 04:35
  • I did all of those things, @Alexander. Alas, no luck. – Dylan Sep 26 '19 at 04:46
  • @matt I was able to reproduce it. Please see the UPDATE above. – Dylan Sep 28 '19 at 06:45
  • The bug is easily reproducible. Better send a bug report as soon as possible. – OOPer Sep 28 '19 at 12:49
  • Great work, well done! – matt Sep 28 '19 at 16:15
  • Struggled with this for hours. Created test cases, etc., until finding this post. It's still an issue but the one way around it is to use NSDate instead of Date. The issue is absolutely the date even if it is not an optional. – C6Silver Dec 04 '19 at 01:16
  • It can be revealed by mapping the object to obj-c, e.g. `latestOpenReport?.controlPackagesValidTo as NSDate` – KlimczakM Jun 08 '20 at 09:28

2 Answers2

17

It appears I've found a bug in Xcode 11. It's easily reproducible as outlined in the UPDATE above. I've filed the bug with Apple.

I'm still looking for a workaround now, since I use quite a few structs containing Date variables. If anybody can find one, please comment below.

Dylan
  • 2,015
  • 1
  • 17
  • 28
  • 2
    Probably the same bug as this question: https://stackoverflow.com/questions/58155061/convert-string-to-url-why-is-resulting-variable-nil In that one, the situation is completely different, but again we have a `nil` shown in the debugger when in fact the thing is not `nil` at all. – matt Sep 29 '19 at 15:08
  • 1
    Just found the same bug. https://stackoverflow.com/questions/58636312/decoder-decode-setting-valid-iso8601-date-as-nil/58653084#58653084 ... I was debugging and spent hours trying to re-work the code. I had too much trust in what the debugger was telling me. It wasn't nil at all... Ughhhh – user1060500 Nov 01 '19 at 01:36
  • @user1060500 Annoying isn't it? I'd encourage you to report it to Apple, and track https://bugs.swift.org/browse/SR-11593, which is where the bug report matt submitted below seems to have landed. – Dylan Nov 01 '19 at 12:51
  • These reported bugs show status as resolved, but I'm on Version 11.2.1 (11B500) and still experiencing the same bug, but even worse – Ron Srebro Nov 19 '19 at 00:40
  • As of now this one still is open: https://bugs.swift.org/browse/SR-11593. Not sure when any of this will roll into Xcode anyway. Seems we might just have to keep reporting this to Apple directly with each release. I find it's still an impediment to development. – Dylan Nov 19 '19 at 04:23
  • 2
    Still occurring for me in Xcode 12.3 . – Dave Hubbard Dec 24 '20 at 21:19
  • 1
    Still facing this issue in XCode 12 – touti Jan 13 '21 at 09:13
14

The cause of the bug is not that var start_time: Date? is present or absent, but that Date is a Swift Foundation overlay. If you remove the Codable conformance and make start_time an NSDate?, everything is fine. So clearly LLDB gets confused by Swift overlay types like Date?.

In this linked question, we see the same issue with URL?. If we change it to NSURL? everything is fine.

I'm not saying that that's a viable workaround! You want and need to use Swift types. I'm just saying that this is what is messing up LLDB. You can include that info when you report the bug.

This bug is slated to be fixed in Xcode 12.5.

matt
  • 447,615
  • 74
  • 748
  • 977