Swift Error When Trying to Access Dictionary: 'Could Not Find Member 'Subscript''

Swift error when trying to access Dictionary: `Could not find member 'subscript'`

Let's take a look at

response["current_rates"][exchange][currency]

response is declared as Dictionary<String,Any>(), so after the first subscript you try to call another two subscripts on an object of type Any.

Solution 1. Change the type of response to be a nested dictionary. Note that I added the question marks because anytime you access a dictionary item you get back an optional.

var response = Dictionary<String,Dictionary<String,Dictionary<String, Float>>>()

func valueForCurrency(currency :String, exchange :String) -> Float? {
return response["current_rates"]?[exchange]?[currency]
}

Solution 2. Cast each level to a Dictionary as you parse. Make sure to still check if optional values exist.

var response = Dictionary<String,Any>()

func valueForCurrency(currency :String, exchange :String) -> Float? {
let exchanges = response["current_rates"] as? Dictionary<String,Any>

let currencies = exchanges?[exchange] as? Dictionary<String,Any>

return currencies?[currency] as? Float
}

Why do I get this error in Swift Could not find member subscript

I suspect your problem is that result is an optional type. option-click on the result variable. If it is of type NSDictionary? or something like [NSObject: AnyObject]? then result will have to be unwrapped before you can use it. I would first try:

if let location = result?["location"]?["name"] as? String {
//do something
}

If result is AnyObject or AnyObject?, I would suggest taking this a step at a time:

if let dict = result as? NSDictionary {
if let location = dict["location"] as? NSDictionary {
if let name = location["name"] as? String {
// use name
}
}
}

You can compact the above into a single if:

if let name = ((result as? NSDictionary)?["location"] as? NSDictionary)?["name"] as? String {
// use name
}

Type 'Any' has no subscript members when accessing dictionary in UserDefaults

The reason of showing this error in your code is: the compiler cannot recognize result as dictionary, if you tried to option and click on result you would see that its type is Any. You have to cast it first as [String: AnyObject] and then get "Authorities" form it.

It should be like this:

if let result = UserDefaults.standard.dictionary(forKey: "dict") {
print(result)
}

That's how you should "optional binding" the dictionary, thus (assumeing that "Authorities" is a [String: String]):

if let addresses = result["Authorities"] as? [String: String] {
print(addresses)
}

You could also do it as one step:

if let result = UserDefaults.standard.dictionary(forKey: "dict"),
let addresses = result["Authorities"] as? [String: String] {
print(result)
print(addresses)

let levelAccess = addresses["levelAccess"]
print(levelAccess) // optional
}

Finally, you could get the levelAcess from addresses as:

let levelAccess = addresses["levelAccess"]

Again, note that levelAccess would be an optional string (String?), which means you should also handle it.

Swift Dictionary access value through subscript throws Error

Issue is solved by explicitly specifying the Type of objects the array contains, In my case it was Array<[String:Any]>

if let detailsObj = dictionary[Keys.details] as? Array<[String:Any]> { //we should also specify what type is present inside Array

}

Credits: @Hamish, @Dávid Pásztor

Thanks!

In Swift getting error Ambiguous reference to member 'subscript'

try to cast keyValue to Key. For example:

extension Dictionary where Key: ExpressibleByStringLiteral, Value: AnyObject {
func getValueForKeyPath(keyValue : String) -> String{
return ((self[keyValue as! Key] as? Dictionary<String,String>) ?? ["":""])?["text"] ?? ""
}
}

type 'Any' has no subscript members

snapshot.value has a type of Any. A subscript is a special kind of function that uses the syntax of enclosing a value in braces. This subscript function is implemented by Dictionary.

So what is happening here is that YOU as the developer know that snapshot.value is a Dictionary, but the compiler doesn't. It won't let you call the subscript function because you are trying to call it on a value of type Any and Any does not implement subscript. In order to do this, you have to tell the compiler that your snapshot.value is actually a Dictionary. Further more Dictionary lets you use the subscript function with values of whatever type the Dictionary's keys are. So you need to tell it you have a Dictionary with keys as String(AKA [String: Any]). Going even further than that, in your case, you seem to know that all of the values in your Dictionary are String as well, so instead of casting each value after you subscript it to String using as! String, if you just tell it that your Dictionary has keys and values that are both String types (AKA [String: String]), then you will be able to subscript to access the values and the compiler will know the values are String also!

guard let snapshotDict = snapshot.value as? [String: String] else {
// Do something to handle the error
// if your snapshot.value isn't the type you thought it was going to be.
}

let employerName = snapshotDict["employerName"]
let employerImage = snapshotDict["employerImage"]
let uid = snapshotDict["fid"]

And there you have it!

Swift Subscript Error

NSDictionary accessed from Swift is an interesting beast.

As long as Swift only knows something is an NSDictionary (not a more specific [Key: Value] Swift-style dictionary), you can only retrieve AnyObject?s out of it.

let dictTemp: NSDictionary = // from somewhere...

let step1 = dictTemp[0] // step1 is an AnyObject?

But then, since you've imported Foundation, you can keep going with a magical subscript operator that works on AnyObject, and checks whether the thing is a dictionary:

let step2 = step1?["source"] // step2 is any AnyObject??

Here's where it gets interesting, because

  • if step1 was a dictionary with a "source" key inside it, step2 will be the corresponding value.
  • if step1 was a dictionary without a "source" key, step2 will be nil — in particular, it's AnyObject??.Some(AnyObject?.None).
  • if step1 was nil (the original dictionary didn't have 0 as a key), or not a dictionary (it had a 0 key with some other kind of value), then step2 will be nil — in particular, AnyObject??.None.

(The distinction between the last 2 cases is mostly unimportant and you shouldn't worry about it, but if you're interested you can see it by using dump).

And of course, we can apply the same principle again:

let step3 = step2??["sourceUrl"] // step3 is AnyObject?? again

Now, binding them all in one if:

if let url = dictTemp[0]?["source"]??["sourceUrl"] as? String {
// do something with url...
}

Caveat

This type of syntax can be dangerous, since it works with arrays and dictionaries at the same time. What would you expect in these situations?

let dict: NSDictionary = [0: ["source": [3: "result"]]]

dict[0]?["source"]??[3] // returns nil (surprise!)
dict[0]?["source"]??[3 as NSNumber] // returns "result"

let dict2: NSDictionary = [0: ["source": [8, 7, 6, 5, 4]]]

dict2[0]?["source"]??[3] // returns 5
dict2[0]?["source"]??[3 as NSNumber] // returns nil (surprise!)

Access to Dictionary values inside Array in swift

println(menuItems[0]["data"]!["name"])

Short answer: menuItems[0]["data"] returns an optional dictionary.

You can look at the below REPL output to understand the issue.

  1. sets up the object.
  2. shows that the array returns a regular dictionary. If the index is out of range, an error will be thrown instead of returning an optional dictionary.
  3. shows that accessing a key in a dictionary that does not exist will return nil
  4. shows that accessing a key in a dictionary will return an optional of its value type. For instance, if a dictionary is storing Strings in its values, it will return a String? when indexed into.
  5. shows that we cannot use subscripts on an optional dictionary.
  6. shows that we can force the optional dictionary to be a dictionary because we know it is not nil. The REPL shows us that the new return type is Dictionary<String, String>
  7. shows that we can then use subscripts to get at the innermost values, and this returns an optional string to us. Optional strings are printable, so my code above doesn't need a second !.
  8. shows that if we force both dictionary return types to their non-optional types, we get a regular value back (a string).

In real code, you would probably want to check for optionals, and handle nils accordingly.

1> let menu: Dictionary<String, Dictionary<String, String>>[] = [["dict1" : ["key" : "val"]], ["dict2" : ["key" : "val"]]]

menu: Dictionary<String, Dictionary<String, String>>[] = size=2 {
[0] = {
[0] = {
key = "dict1"
value = {
[0] = {
key = "key"
value = "val"
}
}
}
}
[1] = {
[0] = {
key = "dict2"
value = {
[0] = {
key = "key"
value = "val"
}
}
}
}
}

2> menu[0]

$R1: Dictionary<String, Dictionary<String, String>> = {
[0] = {
key = "dict1"
value = {
[0] = {
key = "key"
value = "val"
}
}
}
}

3> menu[0]["key"]

$R2: Dictionary<String, String>? = nil

4> menu[0]["dict1"]

$R3: Dictionary<String, String>? = Some {
[0] = {
key = "key"
value = "val"
}
}

5> menu[0]["dict1"]["key"]

REPL:6:1: error: could not find member 'subscript'
menu[0]["dict1"]["key"]
^~~~~~~~~~~~~~~~~~~~~~~

6> menu[0]["dict1"]!

$R4: Dictionary<String, String> = {
[0] = {
key = "key"
value = "val"
}
}

7> menu[0]["dict1"]!["key"]

$R5: String? = "val"

8> menu[0]["dict1"]!["key"]!

$R6: String = "val"


Related Topics



Leave a reply



Submit