Is it possible to filter an array of [AnyObject] to yield all elements of a given type, and none other?
I can do it if the type is known at compile time:
class MyClass1: CustomStringConvertible {
var value: Int
var description: String {
return "MyClass1: \(value)"
}
init(_ value: Int) {
self.value = value
}
}
class MyClass2: CustomStringConvertible {
var value: Int
var description: String {
return "MyClass1: \(value)"
}
init(_ value: Int) {
self.value = value
}
}
class MySubClass1: MyClass1 {
override var description: String {
return "MySubClass1: \(value)"
}
}
let a1 = MySubClass1(1)
let a2 = MySubClass1(2)
let b1 = MyClass1(3)
let b2 = MyClass2(4)
let array: [AnyObject] = [a1, b1, a2, b2]
func getClass1ObjectsFromArray(_ array: [AnyObject]) -> [MyClass1] {
return array.compactMap( { $0 as? MyClass1 })
}
func getSubClass1ObjectsFromArray(_ array: [AnyObject]) -> [MySubClass1] {
return array.compactMap( { $0 as? MySubClass1 })
}
print(getClass1ObjectsFromArray(array))
print(getSubClass1ObjectsFromArray(array))
Prints:
[MySubClass1: 1, MyClass1: 3, MySubClass1: 2]
[MySubClass1: 1, MySubClass1: 2]
For every type I want to filter on, I had to write a separate function. This looks ugly to me, and will not work when the type to be selected for is only known at run time.
Question:
Is there a generic way to write such a function? Preferably something like:
func getObjectsOfType(_ type: TypeExpression, fromArray array: [AnyObject])
-> [TypeExpression] {
...
}
Or any other way to achieve this?
Thanks for any help!
I think you could use something like this...
This will filter the array and return a typed array containing only the type you want.
Caveat
Having said that. In Swift you should be avoiding heterogeneous arrays where possible. Arrays should really only contain one type of item.
A bit of code testing...
Tested in Playground...
Output:
Edit 1
You could also create a generic function something like this...
This will then filter based on the type of the output array that you want.
I'm not sure what you mean by only knowing the type you want at run time. Can you give a more concrete example of what you mean?
Edit 2
Another possibility is a generic function like this...
This uses the type information of the second parameter to filter the array by that type of item.
Edit 3
If you don't like passing in an instance of the type then you can pass the type itself...
But I'm not sure what more you're getting from this than just filtering by string in the first place?