Instantiated optional variable shows as nil in Xco

2020-01-27 07:11发布

问题:

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:

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

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

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.

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/?

回答1:

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.



回答2:

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.