4

In my Swift code, I am trying to instantiate an Objective-C view controller like below, however the viewDidLoad method is not being called.

let detailMessageVC = DetailMessageViewController(nibName:nil, bundle:nil)

If I instantiate the same viewcontroller from Objective-C code like this it does get called. There is no xib for the view controller.

self.detailMVC = [[DetailMessageViewController alloc] init];

Does anyone know why this is happening? I would like to have the same behaviour when calling from Swift as I rely on the viewDidLoad to perform various initialisation. This is with Xcode 6.3.2

rmaddy
  • 314,917
  • 42
  • 532
  • 579
tech74
  • 1,609
  • 1
  • 20
  • 39
  • I don't see you presenting the view controller. Does it even show up? – saagarjha Aug 16 '15 at 17:48
  • 3
    `viewDidLoad` shouldn't be called for either of those two lines. `viewDidLoad` is called the first time the `view` property of the view controller is accessed. That doesn't normally happen just by instantiating the view controller. Typically it happens when first trying to display the view controller. – rmaddy Aug 16 '15 at 17:48
  • I you are using [[DetailMessageViewController alloc] init]; then viewDidLoad will not call automatically, you need to call [self.detilVc loadView] – Adnan Aftab Aug 16 '15 at 17:57
  • you probably don't want to call loadView by itself, this can cause a recursive cycle memory leak where viewDidLoad isn't called, you may just want to do something like this if you really need to, but I can't see a case when this is really needed: YOURViewController * so = [[YOURViewController alloc] init]; UIView * what=so.view; this will cause the view to be preloaded and will call ViewDidLoad as wll to prevent side effects, but again, I don't see a reason why you would want to do this very often – Larry Pickles Aug 16 '15 at 18:06
  • 1
    @C_X Never call `loadView` directly. The docs even tell you that. – rmaddy Aug 16 '15 at 18:08
  • the only way you should be calling loadView is like this, and this means you are using programmatic views: -(void)loadView { [self setView:[NSHSplashScreenView new]]; } -(NSHSplashScreenView*)contentView { return (id)[self view]; } – Larry Pickles Aug 16 '15 at 18:09
  • yes and docs also say use initWithNibName:bundle: (if you don't have nib pass nil reset it will handle) – Adnan Aftab Aug 16 '15 at 18:09
  • Ill have to try that one, C_X, from my experience if you call loadView like you show then then view of the view controller doesn't have a point of reference to set it's views and thereby doesn't have a "window" size to work with yet so it crashes, and crashes very badly with a recursive call to itself – Larry Pickles Aug 16 '15 at 18:12

2 Answers2

1

As comment stated, there is no link between initialisation of a view controller and it's viewDidLoad callback.

You can even have viewDidLoad called before init. Because viewDidLoad is called if the ViewController effectively loaded a view.

Check there : https://stackoverflow.com/a/4862772/1486230

Although, I wouldn't rely on viewDidLoad unless you know that you will effectively display your ViewController; Mostly by using myVC.view.

Just think like initialising a ViewController (which is only a logic object) is different than creating its view. For performance reason, iOS won't create the graphic object if they are not needed. If you get a difference between Swift and Objective-C, it's more because Swift is probably better on optimisation. But the behaviour is normal.

Community
  • 1
  • 1
Tancrede Chazallet
  • 7,035
  • 6
  • 41
  • 62
  • The behavior is normal but sometimes you need to tell UIKit to load the view if this hasn't been done. Mostly when using Xib. This is done by calling vc.loadViewIfNeeded() – iDev Jul 13 '17 at 14:15
0

For iOS 9+ you can call vc.loadViewIfNeeded().

iDev
  • 503
  • 5
  • 25