Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type '[String, AnyObject?]' does not conform to protocol AnyObject?: why?

I'm trying to understand why I have a compilation error: Type '[String, AnyObject?]' does not conform to protocol AnyObject?

var cars: [String: AnyObject?] = [ "model": "Ferrari"]
var JSON: [String: AnyObject?] = [ "cars": cars ]  // <-- error

It seems like cars is not an AnyObject? which I don't understand.

Thanks for your help!

like image 804
Kamchatka Avatar asked Sep 23 '14 14:09

Kamchatka


2 Answers

AnyObject must be a class, but Dictionary is a structure.

The Swift Programming Language: Type Casting

AnyObject can represent an instance of any class type.

The Swift Programming Language: Classes and Structures

Swift’s String, Array, and Dictionary types are implemented as structures.


You can use Any? for this purpose.

var cars: [String: Any?] = [ "model": "Ferrari"]
var JSON: [String: Any?] = [ "cars": cars ]

After looking at this a bit more, there is a subtle problem which causes this to break.

Here is a sample which works:

var cars: [String: AnyObject] = [ "model": "Ferrari"]
var JSON: [String: AnyObject] = [ "cars": cars ]

It works because cars is coerced (implicitly cast) from [String: AnyObject] to an object compatible with NSDictionary ([AnyHashable: AnyObject]). This NSDictionary compatible object is then cast to AnyObject. So, magic.

[String: AnyObject?] cannot be cast in this way because it not NSDictionary compatible, so the coercion fails.

like image 200
Jeffery Thomas Avatar answered Sep 25 '22 09:09

Jeffery Thomas


It seems like cars is not an AnyObject?

You defined cars as of type [String: AnyObject?], thus, the following code is valid (tested in Playground):

var cars: [String: AnyObject?] = [ "model": "Ferrari"]
var JSON: [String: [String: AnyObject?]] = [ "cars": cars ]

You should define JSON as of type [String: AnyObject?] or [String: Any?] (according to your needs) only if you can't guess what type cars will be (see Type Casting for Any and AnyObject in The Swift Programming Language).

Will that impact the casting of my object towards a NSDictionary?

NSDictionary can't hold nil (see here or here). The following code gives an error message in Playground:

var nsDict1: NSDictionary = [12 : 10, 10 : nil] //eror message

var cars: [String: AnyObject?] = [ "model" : nil]
var JSON: [String: [String: AnyObject?]] = [ "cars" : cars ]
let nsDict2 = JSON as NSDictionary //error message

However, the following code is valid:

var nsDict1: NSDictionary = [12 : 10, 10 : NSNull()] //no error message

var cars: [String: AnyObject] = [ "model" : "Ferrari"] //also works with [ "model" : NSNull()]
var JSON: [String: [String: AnyObject]] = [ "cars" : cars ]

let nsDict2 = JSON as NSDictionary //no error message
like image 33
Imanou Petit Avatar answered Sep 23 '22 09:09

Imanou Petit