2
votes

How can I check in Swift if a value is an Array. The problem is that an array of type Int can apparently not be casted to an array of type Any. Suppose I have an array myArray of type Int and execute the following:

if let array = myArray as? [Any] { return true }

it doesn't return true (which surprises me actually). The same thing appears with dictionaries. I want a dictionary of type String, Any (meaning that Any can be any type). How can I check if it is?

Thanks in advance.

4
Interesting, I cannot get it to work as wellKametrixom
Can you give an example of how such a downcast would be useful? Every type implicitly conforms to Any, so what your statement is effectively saying is "If this array is an array, return true"... the compiler is already well aware that it is an array.Stuart
@Stuart I want to parse JSON -- in fact I don't return true but do something with the array then. Anyway, the question has been resolved, see belowborchero
Ah, so in your code myArray would be an object that is not of type Array. NSJSONSerialization produces object types, so a scalar integer would be a NSNumber - this allows you to use AnyObject regardless of the value in the JSON array/dictionary.Stuart
No, sorry for the confusion but I want to be able to convert simple dictionaries to JSON, too. This is why I can't use AnyObjectborchero

4 Answers

3
votes

Got it working like this, although it's not as beautiful as I would've hoped:

protocol ArrayType {}
extension Array : ArrayType {}

let intArray : Any = [1, 2, 3]
let stringArray : Any = ["hi", "hello", "world"]

intArray is ArrayType       // true
stringArray is ArrayType    // true

EDIT: I think I misunderstood your question before, now I got it though:

let intArray = [1, 2, 3]

let anyArray = intArray.map{ $0 as Any }

This is the only way to my knowledge.

0
votes

Got it now, with the idea of @Kametrixom. It's extraordinary ugly but at least it works.

private protocol CJSONArrayType {
    func toAny() -> [Any]
}
extension Array: CJSONArrayType {
    private func toAny() -> [Any] {
        return self.map { $0 as Any }
    }
}
extension NSMutableArray: CJSONArrayType { }
extension NSArray: CJSONArrayType {
    private func toAny() -> [Any] {
        var result = [Any]()
        for item in self {
            result.append(item as Any)
        }
        return result
    }
}

private protocol CJSONDictionaryType {
    func toStringAny() -> [String: Any]
}
extension Dictionary: CJSONDictionaryType {
    private func toStringAny() -> [String : Any] {
        var result = [String: Any]()
        for item in self {
            result[item.0 as! String] = item.1 as Any
        }
        return result
    }
}
extension NSMutableDictionary: CJSONDictionaryType { }
extension NSDictionary: CJSONDictionaryType {
    private func toStringAny() -> [String : Any] {
        var result = [String: Any]()
        for item in self {
            result[item.0 as! String] = item.1 as Any
        }
        return result
    }
}
0
votes

If you want to parse JSON, there are only a few supported types which are at least AnyObject rather than Any.

Then it's very easy to check for Array

func checkArray(item : AnyObject) -> Bool {
  return item is Array<AnyObject>
}

let integer = 1
let string = "one"
let array = ["one", "two", "three"]
let dictionary = ["one" : 1, "two" : 2]

checkArray(integer) // false
checkArray(string) // false
checkArray(array) // true
checkArray(dictionary) // false

Apple highly recommends to constrain the types at compile time as much as possible

0
votes

You can simply

array is Array<Any>