How to call a generic function with a dynamic type in Swift

Say I have a Fooable protocol:

 protocol Fooable {} 

Now I need to work with the Fooable type in a generic function:

 func fooingAround<FooableType: Fooable>(withType: FooableType.Type) {} 

This works fine when I just call a function with type Fooable :

 struct Foo: Fooable {} fooingAround(Foo.self) // works fine 

However, I need to get the type Fooable , which I pass to the function from another place. Here the compiler does not work:

 let fooableType: Fooable.Type = // obtain from somewhere else fooingAround(fooableType) // compiler error: "Cannot invoke 'fooingAround' with an argument list of type '(Fooable.Type)'" 

In particular, I get Fooable.Type from an enumeration that describes the API endpoints, where each endpoint is represented by a different Fooable class.

I assume that the problem arises because I am dynamically getting the type, so there can be no strong input at compile time.

Is there any way around this?

+5
source share
1 answer

The problem is this:

 let fooableType: Fooable.Type = // obtain from somewhere else 

... throws into oblivion exactly the information that you want to save in this variable, that is, the specific type corresponding to Fooable . Note that the following code compiles:

 protocol Fooable {} func fooingAround<FooableType: Fooable>(withType: FooableType.Type) {} struct Foo: Fooable {} fooingAround(Foo) // works fine let foo = Foo() let fooableType /* do not cast here */ = foo.dynamicType fooingAround(fooableType) // also works fine 

... that means you need to find a way to directly pass type information into your function call without casting.

Depending on the type of fooingAround that you have in mind, you can, for example, extend Fooable along the following lines:

 extension Fooable { func fooingAround() { /* do some fooing with */ self.dynamicType // which is the Foo.Type when called on the `foo` value } } foo.fooingAround() 
+1
source

Source: https://habr.com/ru/post/1246175/


All Articles