11

A picture is worth a thousand words, how to rewrite this code from Objective-C to Swift?

- (id) instanceOfClass: (Class) class withInitializer: (SEL) initializerSelector withObject: (id) object {
    id obj = nil;
    if([class instancesRespondToSelector:initializerSelector]) {
        obj = [[class alloc] performSelector:initializerSelector
                                  withObject:object];
    }
    return obj;
}

id myViewController = [self instanceOfClass:[ViewController class]
                              withInitializer:@selector(initWithObject:)
                                   withObject:@"super-string!"];
NSLog(@"%@", myViewController);
karolszafranski
  • 702
  • 8
  • 17
  • The difficulty is not with dynamic class, but rather with dynamic selector. It is possible to create instances with a dynamic class in Swift, with a fixed initializer. However, calling methods (or initializers in this case) with dynamic selector is generally impossible in Swift, because it is fundamentally unsafe (the selector doesn't carry type information of the called method). – newacct Jan 09 '15 at 03:16

3 Answers3

5

This cannot be done purely in Swift. You can only do this by creating the "class instance by name creator" in Objective C and calling this code from Swift.

For more information you can read this article. http://ijoshsmith.com/2014/06/05/instantiating-classes-by-name-in-swift/

And check out this github repo https://github.com/ijoshsmith/swift-factory

rakeshbs
  • 24,392
  • 7
  • 73
  • 63
1

If you can make your classes subclasses of a common superclass you can do this:

class C {
  var typ:String
  init() {
    self.typ = "C"
  }
  class func newInst() -> C {
    return C()
  }
}

class C1 : C {
  override init() {
    super.init()
    self.typ = "C1"
  }
  override class func newInst() -> C1 {
    return C1()
  }
}

class C2 : C {
  override init() {
    super.init()
    self.typ = "C2"
  }
  override class func newInst() -> C2 {
    return C2()
  }
}

var CL:C.Type = C1.self
CL = C2.self
var inst = CL.newInst()

inst.typ

If not then you can use a closure or block to create the instance and place those in a dictionary by name.

Michael Latta
  • 47
  • 1
  • 4
0

See matt's excellent answer here. Basically with @objc you can mimic the dynamic creation of instances.

Community
  • 1
  • 1
qwerty_so
  • 35,448
  • 8
  • 62
  • 86