Value of type 'Any' has no subscripts

Hi!

I am very new to xcode and I am working on a shopping list program that I have followed through a tutorial online. I am currently getting this error and I am unsure what I have missed.

Any help is appreciated. Thanks so so much!

    let ud = UserDefaults.standard
     
    if !ud.bool(forKey: "UserDefaultsSeedItems") {
      if let filePath = Bundle.main.path(forResource: "seed", ofType: "plist"), let seedItems = NSArray(contentsOfFile: filePath) {
        // Items
        var items = [Item]()
         
        // Create List of Items
        for seedItem in seedItems {
          if let name = seedItem["name"] as? String, let price = seedItem["price"] as? Float { //2 Errors here; "Value of type 'Any' has no subscripts"
            print("\(name) - \(price)")
             
            // Create Item
            let item = Item(name: name, price: price)
             
            // Add Item
            items.append(item)
          }
        }
         
        print(items)
         
        if let itemsPath = pathForItems() {
          // Write to File
          if NSKeyedArchiver.archiveRootObject(items, toFile: itemsPath) {
            ud.set(true, forKey: "UserDefaultsSeedItems")
          }
        }
      }
    }
  }
Answered by Claude31 in 733525022

@JZX_AP You don't answer all questions, so it is harder to help.

What did print("seedItems", seedItems) actually print?

But maybe seedItem needs to be cast to Item

            for seedItem in seedItems {
                   if let seed = seedItem as? Item {
                       let name = seed.name //ERROR Value of type 'Any' has no member 'name'
                       let price = seed.price //ERROR Value of type 'Any' has no member 'price'
                       print("\(name) - \(price)")
               
                      // Create Item
                      let item = Item(name: name, price: price)
               
                      // Add Item
                       items.append(item)
                   }

Question: why do you need to create a new Item and not just reuse seed ?

How is seedItems defined ? It is an array of what type of items ? Please show so that we can help.

        for seedItem in seedItems {
          if let name = seedItem["name"] as? String, let price = seedItem["price"] as? Float { //2 Errors here; "Value of type 'Any' has no subscripts"

seedItem is one item in seedItems. It is not an array nor a dictionary (seedItems is an array).

May be what you want is access a property of item like this:

        for seedItem in seedItems {
          if let name = seedItem.name as? String, let price = seedItem.price as? Float { //2 Errors here; "Value of type 'Any' has no subscripts"

or simply, if they are not optional:

        for seedItem in seedItems {
             let name = seedItem.name 
             let price = seedItem.price

So please show more code so that we can confirm.

Thank you for the reply! I am following this tutorial here if this helps you understand my problem more, https://code.tutsplus.com/tutorials/ios-from-scratch-with-swift-building-a-shopping-list-application-1--cms-25515

It has grocery items in the array

Here is the code for the Item class, let me know if you need other code. Sorry I am a beginner so I'm unsure what is needed.


import UIKit

class Item: NSObject, NSCoding {
  func encode(with coder: NSCoder) {
    coder.encode(uuid, forKey: "uuid")
    coder.encode(name, forKey: "name")
    coder.encode(price, forKey: "price")
    coder.encode(inShoppingList, forKey: "inShoppingList")
  }
   

  var uuid: String = NSUUID().uuidString
  var name: String = ""
  var price: Float = 0.0
  var inShoppingList = false

  // MARK: -
  // MARK: Initialization
  init(name: String, price: Float) {
    super.init()
     
    self.name = name
    self.price = price
  }

  // MARK: -
  // MARK: NSCoding Protocol
  required init?(coder decoder: NSCoder) {
    super.init()
     
    if let archivedUuid = decoder.decodeObject(forKey:)("uuid") as? String {
      uuid = archivedUuid
    }
     
    if let archivedName = decoder.decodeObject(forKey:)("name") as? String {
      name = archivedName
    }
     
    price = decoder.decodeFloat(forKey:)("price")
    inShoppingList = decoder.decodeBool(forKey:)("inShoppingList")
  }
   
  func encodeWithCoder(coder: NSCoder) {
    coder.encode(uuid, forKey: "uuid")
    coder.encode(name, forKey: "name")
    coder.encode(price, forKey: "price")
    coder.encode(inShoppingList, forKey: "inShoppingList")
  }

}

Could add a print:

      if let filePath = Bundle.main.path(forResource: "seed", ofType: "plist"), let seedItems = NSArray(contentsOfFile: filePath) {
          print("seedItems", seedItems)
        // Items

and post what you get.

Solution is likely to be

        for seedItem in seedItems {
             let name = seedItem.name 
             let price = seedItem.price

Thanks for the help, im getting a few more errors now which I put comments next to so you can see

    let ud = UserDefaults.standard
     
    if !ud.bool(forKey: "UserDefaultsSeedItems") {
      if let filePath = Bundle.main.path(forResource: "seed", ofType: "plist"), let seedItems = NSArray(contentsOfFile: filePath) {
           print("seedItems", seedItems)
          // Items
          var items = [Item]()
           
          // Create List of Items
            
            for seedItem in seedItems {
                   let name = seedItem.name //ERROR Value of type 'Any' has no member 'name'
                   let price = seedItem.price //ERROR Value of type 'Any' has no member 'price'
              print("\(name) - \(price)")
               
              // Create Item
              let item = Item(name: name, price: price)
               
              // Add Item
              items.append(item)
            }
          }
         
        print(items) //ERROR Cannot find 'items' in scope
         
        if let itemsPath = pathForItems() {
          // Write to File
          if NSKeyedArchiver.archiveRootObject(items, toFile: itemsPath) { //ERROR Cannot find 'items' in scope
            ud.set(true, forKey: "UserDefaultsSeedItems")
          }
        }
      }
    }
  }

What did print("seedItems", seedItems) actually print?

Accepted Answer

@JZX_AP You don't answer all questions, so it is harder to help.

What did print("seedItems", seedItems) actually print?

But maybe seedItem needs to be cast to Item

            for seedItem in seedItems {
                   if let seed = seedItem as? Item {
                       let name = seed.name //ERROR Value of type 'Any' has no member 'name'
                       let price = seed.price //ERROR Value of type 'Any' has no member 'price'
                       print("\(name) - \(price)")
               
                      // Create Item
                      let item = Item(name: name, price: price)
               
                      // Add Item
                       items.append(item)
                   }

Question: why do you need to create a new Item and not just reuse seed ?

Sorry I am still new so some of the questions are hard for me to understand, that worked perfectly thank you so much for all the help!!!!

Value of type 'Any' has no subscripts
 
 
Q