Hi,
I would like to transform the metatype of any given nested array of arbitrary depth to the metatype of another nested array.
What I mean with that is the following:
I have a class Wrapper and I have nested arrays of arbitrary depth of any type. Let's say the nested array's innermost type is SomeClass, i.e. metatypes are [SomeClass].self, [[SomeClass]].self, [[[SomeClass]]].self, ... . I now want to take those metatypes and transform them to [Wrapper].self, [[Wrapper]].self, [[[Wrapper]]].self, ...
So essentially I am looking for a function that transforms a given metatype of an array of arbitrary depth like this: [SomeClass].self -> [Wrapper].self [[SomeClass]].self -> [[Wrapper]].self [[[SomeClass]]].self -> [[[Wrapper]]].self ...
Any ideas on how to do that?
My best attempt so far is the following:
// Wrapper class for output
class Wrapper { }
// protocol to identify array and get its Element type
protocol ArrayProtocol {
static var elementType: Any.Type { get }
}
// get elementType
extension Array: ArrayProtocol {
static var elementType: Any.Type {
return Element.self
}
}
// function that does the actual transform
func transformType(_ input: Any.Type) -> Any.Type {
func transformTypeRecursive(_ input: Any.Type) -> Any {
if let arrayType = input as? ArrayProtocol.Type {
return [transformTypeRecursive(arrayType.elementType)]
} else {
return Wrapper()
}
}
return type(of: transformTypeRecursive(input))
}
Unfortunately this does not work as transformType does not maintain the type of the recursively constructed arrays (following is example for nested array of depth 2 with arbitrary class SomeClass):
class SomeClass { }
transformType([[SomeClass]].self) is [[Wrapper]].Type // yields false, but obviously I'd like this to be true
func transform(_ value: Any, using callback: (Any) -> Any) -> Any {
if let a = value as? Array<Any> {
return a.map { v in
transform(v, using: callback)
}
} else {
return callback(value)
}
}
transform([[[SomeClass()]]]) { value in
_ x = value as! SomeClass
// ...
let wrapper = Wrapper(...)
return wrapper
}
Thanks for the reply. Unfortunately your code also removes the underlying specific type information due to working with Any. Or am I missing something?
Running yields
let transformedArray = transform([[[SomeClass()]]]) { value in
return Wrapper()
}
type(of: transformedArray) is [[[Wrapper]]].Type // false, same problem as with my code