Mismatching types 'Int64' and '_' when trying to assign optional Int64 to a dictionary key
Asked Answered
B

4

6

Question regarding Swift 2.1 in Xcode 7.

I have declared an optional variable like this:

var something: Int64?

I would like to later assign it to a dictionary key using a shorthand if, like this:

dictionary['something'] = (something != nil) ? something! : nil

XCode is giving me the following validation error:

Result values in '? :' expression have mismatching types: 'Int64' and '_'

What is the issue here? Why can't optional Int64 be nil?

Boyar answered 20/1, 2016 at 14:20 Comment(5)
what is your dictionary type?Threephase
<String, AnyObject> I also found out that I apparently can't assign Int64 to AnyObject. Why's that?Boyar
AnyObject can only hold class types, whereas Int64 is value type. Also, 'something' is not a string, whereas "something" is.Knossos
Cheers guys, that makes sense. I was also suggested that I should use NSNumber(), so I will probably go for that solution. I didn't realize Int64 is of different type than a regular Int.Boyar
@Travo alternatively, if possible, use Any instead of AnyObject; the prior can hold also value types (e.g. Int64).Knossos
H
7

There are a number of problems here. First, Int64 isn't an AnyObject. None of the primitive number types are classes. They can be bridged to AnyObject using NSNumber, but you don't get that bridging automatically for Int64 (see MartinR's comment. I originally said this was because it was wrapped in an Optional, but it's actually because it's fixed-width).

Next, this syntax:

(something != nil) ? something! : nil

Is just a very complicated way to say something.

The tool you want is map so that you can take your optional and convert it to a NSNumber if it exists.

dictionary["something"] = something.map(NSNumber.init)

Of course, if at all possible, get rid of the AnyObject. That type is a huge pain and causes a lot of problems. If this were a [String: Int64] you could just:

dictionary["something"] = something
Handwork answered 20/1, 2016 at 14:35 Comment(2)
Only Int/UInt (and Float, ...) are implicit bridged to NSNumber, not the fixed sized integer types like Int64 (observed e.g. here: #28177935)Magdeburg
@MartinR Thanks. Fixed.Handwork
S
2

You can't add a Int64 to a dictionary of type [String : AnyObject], you need to wrap in in an NSNumber object. You can only store objects that conform to AnyObject in your dictionary.

var something: Int64?

something = 42

if let myVal: Int64 = something { // unwrap to make sure the value is there
    let myNum = NSNumber(longLong: myVal) // create an NSNumber from your Int64

    dictionary["something"] = myNum // insert it into the dictionary
}

As Anton Bronnikov said below, if your dictionary was type [String : Int64], you would be able to add your Int64 to it no problem.

Simpleminded answered 20/1, 2016 at 14:30 Comment(4)
You can perfectly add Int64 to a dictionary of [String: Int64].Jaggers
@AntonBronnikov the OP's dictionary is of type [String : AnyObject].Simpleminded
@Simpleminded I think someone gave you a downvote due to the "add a Int64 to a dictionary" rather than "... your dictionary".Knossos
Updated my answer to reflect those changes.Simpleminded
K
1

It seems that others have already pointed out the issues with the types in your dictionary. I want to add that you can also use the nil coalescing operator '??' as even more concise shorthand for what you are doing in your example. It is most useful when you want to do a check for nil, (and if non-nil) unwrap the value and assign it, otherwise provide a default value.

var maybeSomething: Int?
var dictionary:[String:Int?] = [:]
dictionary["something"] = maybeSomething ?? nil
Kumiss answered 20/1, 2016 at 14:59 Comment(0)
A
0

something! has type Int64. Not optional Int64, but Int64. nil has type nil. You can't have an expression

condition ? Int64 : nil

What would be the type of it?

And the whole thing is pointless. On the right hand side you would have just "something". If that doesn't work then your dictionary doesn't accept optionals.

PS. Noticed that your dictionary wants to store Objective-C objects. In that case, no way it accepts an optional. And it only accepts an Int64 after converting to NSNumber.

Augmentation answered 20/1, 2016 at 14:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.