14

I created ViewController in Storyboard and I am using

instantiateViewControllerWithIdentifier:

to load it. But I need to have this VC as base class and use 3-4 subclasses to change its properties.

How can I get an instance of my subclass with instantiateViewControllerWithIdentifier?

Kampai
  • 22,848
  • 21
  • 95
  • 95
Mat Demon
  • 197
  • 1
  • 9
  • Here is your [answer](http://stackoverflow.com/questions/28022258/ios-present-viewcontroller-getting-black-screen/28022449#28022449)! – Kampai Sep 14 '15 at 06:08

3 Answers3

20

@Bhagyesh version in Swift 3:

class func instantiateFromSuperclassStoryboard() -> SubclassViewController {
    let stroryboard = UIStoryboard(name: "Main", bundle: nil)
    let controller = stroryboard.instantiateViewController(withIdentifier: "BaseViewController")
    object_setClass(controller, SubclassViewController.self)

    return controller as! SubclassViewController
}
ChikabuZ
  • 10,031
  • 5
  • 63
  • 86
7

You will have to use object c runtime. Override init method of your subclass. Create a BaseViewController object using 'instantiateViewControllerWithIdentifier'. Then set the class for created object using objc_setClass method. Following code will go into SubclassViewController.m.

    - (instancetype)init {
      UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"main" bundle:[NSBundle mainBundle]];
      UIViewController *baseClassViewController = [storyboard instantiateViewControllerWithIdentifier:@"baseClassIdentifier"];

      object_setClass(baseClassViewController, [SubclassViewController class]);
      return (SubclassViewController *)baseClassViewController;
    }

After this, you can simply create SubclassViewController object using simple [[SubclassViewController alloc] init].

Bhagyesh
  • 144
  • 1
  • 8
  • 9
    Sadly, this crashes if the subclass contains any extra instance variables. That's because `object_setClass` simply changes the `isa` pointer. It doesn't allocate any extra space. As soon as you try to access an additional variable, boom. – Jon Reid Oct 21 '17 at 18:11
-1

Just cast it.

MyController *controller = (MyController *)[self.storyboard instantiateViewControllerWithIdentifier:@"myController"];

or Swift:

let controller = storyboard?.instantiateViewControllerWithIdentifier("myController") as! MyController
Daniel T.
  • 32,821
  • 6
  • 50
  • 72
  • But if I need to create MyControllerSubclass1 that subclass of MyController from storyboard with id "myController"? – Mat Demon Sep 14 '15 at 03:40
  • Whatever ID you gave the view controller in the storyboard. – Daniel T. Sep 14 '15 at 12:35
  • No, that won't work in that case, you will get a runtime error: `Could not cast value of type 'YourApp.BaseViewController' (0x10e435d48) to 'YourApp.SubclassViewController' (0x10e435a68).` – Frederic Adda Sep 01 '16 at 09:10