Philippe
Philippe

Reputation: 9742

Cast value to array of unknown `Element` type

Assuming a function that operates on any Array:

func g<T>(array: [T]) -> Void {
  // ...
}

...and a function that receives a value of type Any:

func f(x: Any) -> Void {
  if x is Array {
    // g(?)
  }
}

How can I get a properly typed version of x that I can pass to g?

Note that g doesn't rely (explicitly) on the type T. All it needs is the ability to iterate over the elements, which can be treated as values of type Any. Any solution that rewrites g to remove the type parameter is therefore also acceptable.

Edit: to make things harder, I'd like this to work on Linux, where Swift arrays aren't NSArrays until you've called .bridge() on them.

Upvotes: 0

Views: 140

Answers (2)

Casey
Casey

Reputation: 6701

if you want to keep the generic, you could do this instead:

func g<T>(array: [T]) -> Void {

}

func f(x: Any) -> Void {
    if let array = x as? [Any] {
        g(array)
    }
}

Upvotes: 0

Cristik
Cristik

Reputation: 32784

Warning Please note that the below results are based on my experiments on Mirror and work in Swift 2.1.1 (Xcode 7.1.1). It might be that future Swift versions will change the Mirror behaviour.

If finding out dynamically if the value is an array of any type, you could use Swift's reflection support, via the Mirror struct:

func processArray(array: Any) -> Bool {
    let mirror = Mirror(reflecting: array)
    guard mirror.displayStyle == .Collection else {
        return false
    }

    print("array has \(mirror.children.count) elements")

    return true
}

func f(x: Any) {
    if processArray(x) {
        // i just found an array
    }
}

f([1, 2, 3, "4"]) // prints "array has 4 elements"

Upvotes: 1

Related Questions