kinkee
kinkee

Reputation: 368

Cast class type retrieved from string

I'm trying to read a class from a String and pass its type to a generic function. But it seems like there's no way to achieve this:

protocol Person { ... }
class Student: Person { ... }
class Teacher: Person { ... }

func foo<SomePerson: Person>(param: String, type: SomePerson.Type) { ... }

// Get class from string and pass class type to foo()
let someClass = NSClassFromString("MyApp.Teacher")
foo("someParam", type: someClass.dynamicType)

Trying this I'm getting an error:

Cannot invoke 'foo' with an argument list of type '(String, type: AnyClass.Type)

Is it actually possible to obtain the 'real' type 'Teacher' instead of the generic type 'AnyClass' and pass it to foo()? The classes are read on runtime from a file - so using hard class names when calling foo() is not possible.

Thanks for any advice!

Upvotes: 2

Views: 610

Answers (1)

luk2302
luk2302

Reputation: 57114

If Person is a class as the original question was written:

Since you are making the life for the compiler considerably harder that it needs to be you have to help him a bit. You have to make sure the type is correct before calling the function:

if let actualType = someClass as? Person.Type {
    foo("someParam", type: actualType)
} else {
    // error handling here
}

Which yields the desired working code:

enter image description here


If Person is a protocol:

You are going to have a bad day. The above solution will not work. As far as I can remember your only option is to check for every possible subclass:

if let actualType = someClass as? Student.Type {
    foo("someParam", type: actualType)
} else if let actualType = someClass as? Teacher.Type {
    foo("someParam", type: actualType)
}
// etc.

Upvotes: 3

Related Questions