Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift Generic with type first known at runtime

i have a question about swift and generics. What I try to do is to get an Object with an generic type. But I first know the type at runtime. But to get to the point fast.

New edited block:

Maybe I can do it with the class name? I have a class name as a string. I got it via a Mirror. Can I create a generic instance with that classname in an string?

let classname: String = "ClassA"
let firstA: a<classname> = a<classname>()
//            ^^^^^^^^^      ^^^^^^^^^
//            what to put here???          

New edited block end:

I have two classes with generic types:

This is a protocol my type has to implement:

protocol ToImplement {
    func getTypeForKey(key: String) -> NSObject.Type
}

This is the class I use for my first Generic Type:

class MyClass: ToImplement {
    func getTypeForKey(key: String) -> NSObject.Type {
        if key == "key1" {
            return UIView.self
        } 
        else {
            return UIButton.self
        }
    }
}

this is my first Class with an generic type:

class a<T:ToImplement> {
    func doSomethingWith(obj: T) -> T {

        // the next part usually runs in an iteration and there can be
        // a lot of different types from the getTypeForKey and the number
        // of types is not known

        let type = obj.getTypeForKey("key1")
        let newA: a<type> = a<type>()       // how could I do this? To create a type I do not know at the moment because it is a return value of the Object obj?
        //          ^^^^      ^^^^
        //          what to put here???


        return obj
    }
}

and that is how I would use it:

let mycls: MyClass = MyClass()
let firstA: a<MyClass> = a<MyClass>()
firstA.doSomethingWith(mycls)

Now my question is: Can I create an instance of class a with a generic type I get as a return value of a function? Is that even possible?

If that is not possible, how could I create an instance with an generic type out of an other instance. Something like:

let someA: a<instance.type> = a<instance.type>()

Thank you for your help!

regards

Artur

like image 412
Artur Hellmann Avatar asked Nov 08 '22 22:11

Artur Hellmann


1 Answers

let type = obj.getType

OK, so type is a NSObject.Type. Since NSObject provides init(), you can instantiate this type with

let obj = type.init()  // obj is a NSObject (or subclass)
return obj

Of course, this will fail at runtime if the actual type returned by getType() doesn't implement init().

Another option is to use an associated type:

protocol ToImplement {
    typealias ObjType: NSObject
}

Then you can use it as a generic constraint:

func makeAnObject<T: ToImplement>(obj: T) -> T.ObjType {
    return T.ObjType()
}

This gives basically the same result.

like image 73
jtbandes Avatar answered Dec 06 '22 09:12

jtbandes