7

I have a UIViewController called LaunchController that is launched in my iPhone app when the app first opens:

@interface LaunchController : UIViewController<UINavigationControllerDelegate, UIImagePickerControllerDelegate>

Then, when a button is clicked, I push another view controller:

 MainController *c = [[MainController alloc] initWithImage:image];
 [self presentModalViewController:c animated:NO];

MainController has the following constructor, which I use:

- (id)initWithImage:(UIImage *)img
{
    self = [super init];
    if (self) {
        image = img;
        NSLog(@"inited the image");
    }

    return self;
}

and then it has a viewDidLoad method as follows:

- (void)viewDidLoad
{
    NSLog(@"calling view did load");
    [super viewDidLoad];

    UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
    [self.view addSubview:imageView];
    NSLog(@"displaying main controller");
}

When the program runs, I see that the constructor for MainController is called (due to the output of NSLog), however viewDidLoad never gets called, even though I am calling presentModalViewController. Why is this? Why isn't viewDidLoad being called?

Ravi Gautam
  • 960
  • 2
  • 9
  • 20
CodeGuy
  • 28,427
  • 76
  • 200
  • 317
  • Does MainController have a `loadView` method implemented? – amattn Jan 16 '12 at 06:09
  • No. What should go in loadView? – CodeGuy Jan 16 '12 at 06:10
  • 1
    You don't actually check it if the new view was initiated. Move NSLog within the if-brackets to see if the view was initiated. – dimme Jan 16 '12 at 06:11
  • yes, it was inited. I moved it and it still prints it. – CodeGuy Jan 16 '12 at 06:14
  • Do you have a nib named `MainController.xib` in your project? If you don't, you must override `-loadView` and provide an empty view. – Jason Coco Jan 16 '12 at 06:17
  • Related, if you aren't using nibs :http://stackoverflow.com/questions/8876212/proper-use-of-loadview-and-viewdidload-with-uiviewcontroller-without-nibs-xibs – jrturton Jan 16 '12 at 06:21
  • that link doesn't provide an answer, just another problem. and @JasonCoco, no I don't have a nib. How can I overwrite loadView such that viewDidLoad will be called – CodeGuy Jan 16 '12 at 06:29
  • I'm not actually sure it's your problem, but you can just override `-loadView` and create a view and assign it to `self.view`. Are you using storyboards? – Jason Coco Jan 16 '12 at 06:32
  • I'm not sure. What's a storyboard? – CodeGuy Jan 16 '12 at 06:41

3 Answers3

4

I think it is something as followings. When you need the property of view inside UIViewController, it will be loaded with lazy manner.

- (UIView *)view 
{
   if (_view == nil) {
      [self loadView]; //< or, the view is loaded from xib, or something else.
      [self viewDidLoad];
   }

   return _view;
} 

After the view initialized, it will call viewDidLoad to inform the UIViewController.

AechoLiu
  • 17,522
  • 9
  • 100
  • 118
  • Please don't do this. Apple documentation specifically states that loadView and viewDidLoad should not be called directly. From `loadView`: "You should never call this method directly." – amattn Jan 17 '12 at 18:48
  • 4
    @amattn: You are right. But I just use above codes to describe when the `-viewDidLoad` called. – AechoLiu Jan 18 '12 at 00:10
3

You aren't loading your view controller from a xib file, and from comments you don't have anything in loadView (which is where you would create your view controller's view if you were not using a xib file).

Therefore, your view isn't being loaded, so viewDidLoad is never called.

Typically you would use initWithNibName: to initialise a new view controller, and then set the image after it (so expose the image as a property).

viewDidLoad will be called as soon as your controller's view property is accessed, that is when you display it for the first time or request it (e.g. have some code that calls c.view.

jrturton
  • 118,105
  • 32
  • 252
  • 268
0

The reason viewDidLoad is not being called is because you aren't loading a view.

In your init method:

 self = [super init];

means that you are just creating a naked view from scratch. not loading one from a nib.

try this instead:

self = [super initWithNibName:nil bundle:nil];

If you have a xib or nib file with the same name as the view controller class it should find if. Otherwise, you can just give a nibName that works.

UPDATE:

If you are not using nib files, then the appropriate method is NOT viewDidLoad. You have to implement loadView instead of viewDidLoad.

In your specific case, just put everything that is currently in viewDidLoad into loadView.

amattn
  • 10,045
  • 1
  • 36
  • 33