hyouuu hyouuu - 2 years ago 68
Swift Question

Why doesn't Swift nil-coalescing ternary operator return unwrapped type?

I read that the ternary operator

unwraps an optional if it is not nil, but if I do:

var type: String?
type = "milk"
let certainType = type ?? "melon"

then certainType will still be a
, and if I do

println("it's a \(certainType)")

it will print:

it's a Optional("milk")



Sorry for the confusion - I meant var type: String?

I get that it should print "it's a milk", but what I saw in console is a "it's a Optional("milk")" - anyone else experienced the same issue? Could that be caused by string interpolation?

Asked by @Antonio, here is more context and real code and logging snapshot - type is from Note, which is a NSManagedObject class used to deal with xcdatamodel

class Note: NSManagedObject {
@NSManaged var type: String?

And I have the type set to 'todo' at some point, then have the following code to print them out:

println("type class:\(_stdlib_getDemangledTypeName(note.type))")
let type1 = note.type ?? "note"
let type2: String = note.type ?? "note"

And the output:

type class:Swift.Optional

As you can see, if I don't explicitly mark the type1's type as String, it will print undesired result Optional("todo") - I use the type in a string interpolation to construct a path so it matters

Answer Source

I can't prove what I am going to say, so any feedback is very well appreciated.

The OP asserts that code similar to this:

var type: String? = "milk"
let certainType = type ?? "melon"
println("it's a \(certainType)")

prints an unexpected string:

"it's a Optional("milk")"

whereas it should be:

"it's a milk"

It turns out that happens when the variable is actually a property with the @NSManaged attribute.

I suspect that there is a bug in type inference. The OP states that:

let certainType = type ?? "melon"

prints the wrong result, whereas:

let certainType: String = type ?? "melon"

prints the correct one.

So for some reason, without explicitly indicating the variable type, the nil coalescing operator is returning an optional.

If I change the type of the type variable to either AnyObject or AnyObject?, it actually prints the unexpected result:

var type: AnyObject = "milk"
let certainType = type ?? "melon"
println("it's a \(certainType)")

"it's a Optional(milk)"

My guess is: because the @NSManaged attribute is used, the property is inferred with the wrong type (AnyObject?) when used, unless the correct type is explicitly indicated.

As to why that happens, no idea (besides thinking it's a bug)

Feel free to up or down vote this answer, and most important don't consider it as a solution - I would appreciate feedback though, because I'm curios to know what's going on and whether it's really a bug or not.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download