Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

(String: AnyObject) does not have a member named 'subscript'

Tags:

swift

I've been through similar questions but still do not understand why my code is throwing an error.

var dict = [String:AnyObject]()
dict["participants"] = ["foo", "bar"]
dict["participants"][0] = "baz"

The error is on line 3: (String: AnyObject) does not have a member named 'subscript'

I'm setting the participants key to an array and then trying to update the first element of it without any luck. The code above is shortened for example purposes, but I am using [String:AnyObject] because it is not only arrays that are stored in the dictionary.

It's probably something really trivial but I am still new to Swift. Thanks for any help in advance!

like image 888
Fenda Avatar asked Jan 18 '15 19:01

Fenda


Video Answer


1 Answers

The error message tells you exactly what the problem is. Your dictionary values are typed as AnyObject. I know you know that this value is a string array, but Swift does not know that; it knows only what you told it, that this is an AnyObject. But AnyObject can't be subscripted (in fact, you can't do much with it at all). If you want to use subscripting, you need to tell Swift that this is not an AnyObject but rather an Array of some sort (here, an array of String).

There is then a second problem, which is that dict["participants"] is not in fact even an AnyObject - it is an Optional wrapping an AnyObject. So you will have to unwrap it and cast it in order to subscript it.

There is then a third problem, which is that you can't mutate an array value inside a dictionary in place. You will have to extract the value, mutate it, and then replace it.

So, your entire code will look like this:

var dict = [String:AnyObject]()
dict["participants"] = ["foo", "bar"]
var arr = dict["participants"] as [String] // unwrap the optional and cast
arr[0] = "baz" // now we can subscript!
dict["participants"] = arr // but now we have to write back into the dict

Extra for experts: If you want to be disgustingly cool and Swifty (and who doesn't??), you can perform the mutation and the assignment in one move by using a define-and-call anonymous function, like this:

var dict = [String:AnyObject]()
dict["participants"] = ["foo", "bar"]
dict["participants"] = {
    var arr = dict["participants"] as [String]
    arr[0] = "baz"
    return arr
}()
like image 200
matt Avatar answered Oct 16 '22 06:10

matt