GGirotto GGirotto -4 years ago 136
Swift Question

Cannot subscript a value of type 'inout Array<Array<Any>>

I have a 2D array :

var matrixOfMutableObjects: Array<Array<Any>>

But when i try to check if the value on a certain position of the Array is a enum that i created the compiler complains:
Cannot subscript a value of type 'inout Array<Array<Any>>


if(x < 0 || x > ROWS || y < 0 || y > COLS){
return false;
} else if (matrixOfMutableObjects[x][y] != enumObject.NOTHING){
return false;
}


Why cant i verify if the element in the position x,y of my Array is of the type enumObject.NOTHING that i created??

public enum enumObject {
case NOTHING
case Wall
}

Answer Source

Pattern matching (used for matching cases in enum instances) and equality testing are two different things.

Also, an object wrapped in Any is only known to the compiler as Any, so you need to perform an attempted conversion to a given type prior to applying e.g. pattern matching vs cases of that type (say, if the type converted to is an enum).

E.g.:

public enum enumObject {
    case NOTHING
    case Wall
}

var matrixOfMutableObjects: Array<Array<Any>> = [
    [1, "two"],
    [enumObject.NOTHING, 4.2]
]

let x = 1
let y = 0
// no bounds checking in this simple example!
if case .some(.NOTHING) = matrixOfMutableObjects[x][y] as? enumObject {
    print("Is nothing!")
}

Or, using the ? syntactic sugar:

// ...
if case .NOTHING? = matrixOfMutableObjects[x][y] as? enumObject {
    print("Is nothing!")
}

Note that the outer .some(...) pattern matching (or ? sugar) checks that the attempted conversion of the element to enumObject is successful. If that is the case, an additional pattern matching of is performed for the wrapped object (which is then known to be of type enumObject) to a given case of enumObject (.NOTHING, specifically).


Curiosities of Swift: avoiding the explicit type conversion

As pointed out by @Hamish in a comment below, it seems that enum case pattern matching can actually perform the conditional type casting for you, meaning you needn't resort to the explicit casting and nested pattern matching above (as? and .some(...)/?, respectively), but can simply use pattern matching against the NOTHING case directly, given that you also supply the enum type:

if case enumObject.NOTHING = matrixOfMutableObjects[x][y] {
    print("Is nothing!")
}

Finally, note that the Swift API Guidelines prescribes lowercase enum cases, so you might want to use the cases nothing and wall, rather than NOTHING and Wall, and additionally CamelCase name convention for types (so prefer EnumObject over enumObject).

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download