Ambiguous use of 'subscript'

Hello, I'm trying to read data from a plist file. The file contains a list of food items, each one containing a dictionary such as the foodName, calories, imageName, etc. However,


func loadItems() {
        if let path = Bundle.main.path(forResource: "mealData", ofType: "plist") {
            let tempDict = NSDictionary(contentsOfFile: path)
            let tempArray = (tempDict!.value(forKey: "foodItems") as! NSArray) as Array

            for dict in tempArray {
                let foodName = dict["name"]! as! String //ERROR: Ambiguous use of 'subscript' 
                let calories = dict["calories"]! as! String //ERROR: Ambiguous use of 'subscript'
                let imageName = dict["imageName"]! as! String //ERROR: Ambiguous use of 'subscript'
                let imageSize = dict["imageSize"]! as! String //ERROR: Ambiguous use of 'subscript'
                let imageType = dict["imageType"]! as! String //ERROR: Ambiguous use of 'subscript'
                let imageLink = dict["imageLink"]! as! String //ERROR: Ambiguous use of 'subscript'
   
                let f = FoodItem(name: foodName, calories: calories, imageName: imageName, imageSize: imageSize, imageType: imageType, imageLink: imageLink)
   
                foodItems.append(f)
            }
        }
    }


When I'm trying to iterate through the array created, I'm receiving this error: ✖Ambiguous use of 'subscript' in all the properties (let foodName = dict["name"]! as! String, etc, etc). I'm not sure why because I casted tempArray as an Array previously in the code, so it should be considered as an array but it is not.


Any ideas? Thank you in advance

Accepted Answer

To successfully subscript to an object, `subscript` needs to be definitely declared for the Key type (in your case, it's String).


But in your code, with casting by `as Array`, the Element type is inferred as `AnyObject`, so your `dict` is of type `AnyObject`.

(It's a bit amazing because `NSArray` works as a `Collection` of `Any`.)

You can apply all methods including subscripts imported, so it can easily be ambiguous as multiple classes define their own `subscript`.


To avoid this ambiguity, your `dict` should be explicitly declared as a `Dictionary`, which means your `tempArray` needs to be an `Array` of `Dictionary`, not an `Array` of `AnyObject`.


Try something like this:

func loadItems() {
    if
        let url = Bundle.main.url(forResource: "mealData", withExtension: "plist"),
        let tempDict = NSDictionary(contentsOf: url) as? [String: Any],
        let tempArray = tempDict["foodItems"] as? [[String: Any]] //<-declare `tempArray` as Array of Dictionary
    {
        for dict in tempArray { //<-`dict` is of type `[String: Any]`
            let foodName = dict["name"]! as! String
            let calories = dict["calories"]! as! String
            let imageName = dict["imageName"]! as! String
            let imageSize = dict["imageSize"]! as! String
            let imageType = dict["imageType"]! as! String
            let imageLink = dict["imageLink"]! as! String
          
            let f = FoodItem(name: foodName, calories: calories, imageName: imageName, imageSize: imageSize, imageType: imageType, imageLink: imageLink)
          
            foodItems.append(f)
        }
    } else {
        print("mealData.plist does not exist or broken")
    }
}

Makes sense.

Thank you!

Ambiguous use of 'subscript'
 
 
Q