Reputation:
I tried to ask this question previously but didn't clearly express my question, so I'll try again here. I also noticed a very similar sounding question, but it is asking for something entirely different.
I have the following code:
class Base {
func launch(code1: Int, code2: Int) { ... }
}
class A: Base {}
class B: Base {}
class C: Base {}
let classes = [A.self, B.self, A.self, B.self, C.self]
for cls in classes {
let obj = ???
}
I would like to instantiate an object of type cls
inside the loop and do something with it. I might have duplicates inside the array, as shown. What do I put in place of the ???
to be able to instantiate the proper objects?
Upvotes: 7
Views: 4312
Reputation: 8391
All you need is a required init
, some way to create an instance that will be shared between all Types
you want this to work for. A protocol
that holds an init method will do fine.
Obviously this works simplest when the init
does not require parameters.
Downside is that you do need to downcast the resulting instances.
protocol ZeroParamaterInit {
init()
}
class Base : ZeroParamaterInit {
func launch(code1: Int, code2: Int) { }
required init() {
}
}
class A: Base {}
class B: Base {}
class C: Base {}
let classes : [ZeroParamaterInit.Type] = [A.self,B.self]
var instances : [Any] = []
for cls in classes {
let instance = cls.init()
instances.append(instance)
}
for instance in instances {
if let test = instance as? A {
print("A")
}
if let test = instance as? B {
print("B")
}
if let test = instance as? C {
print("C")
}
}
Upvotes: 6
Reputation: 17534
import Foundation
class Base {}
class A: Base { var i: Int = 1 }
class B: Base { var i: String = "bravo" }
class C: Base { var i: Bool = true }
let classes = [A.self, B.self, A.self, B.self, C.self]
for cls in classes {
var obj: Base? {
switch cls {
case is A.Type:
return A()
case is B.Type:
return B()
case is C.Type:
return C()
default:
return nil
}
}
dump(obj)
}
/*
▿ A
▿ Some: A #0
- super: Base
- i: 1
▿ B
▿ Some: B #0
- super: Base
- i: bravo
▿ A
▿ Some: A #0
- super: Base
- i: 1
▿ B
▿ Some: B #0
- super: Base
- i: bravo
▿ C
▿ Some: C #0
- super: Base
- i: true
*/
this is very close to R Menke solution ...
Upvotes: 0
Reputation: 3077
Alright, you'll love this link: http://ijoshsmith.com/2014/06/05/instantiating-classes-by-name-in-swift/
It walks you through the Swift library Obj ectFactory:
https://github.com/ijoshsmith/swift-factory
You really can't do this in Swift. You can, however, do it in Objective-C so you can simply write a wrapper that exposes a Swift interface where behind the scenes, actual object creation is done in Objective-C. That library is exactly what you're looking for.
You'd need to create a ObjectFactory like this:
let factory = ObjectFactory<MyClass>
Then you can instantiate an instance of MyClass like:
let myClass1 = factory.createInstance(className: "MyClassName")
Upvotes: 0