Steve
Steve

Reputation: 31

viewDidLoad never called in Sub-classed UIViewController

I've run into some trouble with loading a sub-classed UIViewController from a nib. My viewDidLoad function is never called.

The super-class has no nib, but the sub-classes each have their own. i.e.

@interface SuperClass : UIViewController {
}
@end


@interface SubClass : SuperClass{
}
@end
@implementation SubClass
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
}
return self;
}
- (void)viewDidLoad{
// Never called
}

The view is loaded from a nib as follows:

SubClass *scvc = [[SubClass alloc]     initWithNibName:@"SubClass" bundle:nil];
    [self.navigationController pushViewController:scvc animated:YES];
    [scvc release];

There is a nib file with this name and it has it's file owner's class set properly.

viewDidLoad is not called in the child or super. Any ideas?

Upvotes: 0

Views: 772

Answers (4)

shannoga
shannoga

Reputation: 19869

Try to add:

[super viewDidLoad];

Upvotes: 0

Firoze Lafeer
Firoze Lafeer

Reputation: 17143

I'm assuming SuperClass implements loadView. So when your SubClass is asked to loadView, you get your SuperClass' implementation, which overrides the normal nib loading mechanism.

I would rethink your design here. Your SuperClass' behavior is quite different from what you want your SubClass to do. Maybe that's not the best relationship there.

But, if you want, you should be able to at least make it work by doing this in your SubClass.m:

-(void)loadView {

    IMP defaultImp = class_getMethodImplementation([[self superclass] superclass], _cmd);

    /* or alternatively...
    IMP defaultImp = class_getMethodImplementation([UIViewController class], _cmd);
    */

    defaultImp(self, _cmd);
}

This implements a loadView for your subclass that skips over the loadView of your SuperClass and calls the default implementation instead.

IMO, this is ugly and might need to revisited if your class hierarchy expanded. I wouldn't do this in my own app, I would rethink the class hierarchy instead.

Upvotes: 1

Tieme
Tieme

Reputation: 65389

Where is this block located

SubClass *scvc = [[SubClass alloc]     initWithNibName:@"SubClass" bundle:nil];
    [self.navigationController pushViewController:scvc animated:YES];
    [scvc release];

Are you sure it is called ?

I made a testproject to test it and the following works:

In your appDelegate.m file i put the following in the application didFinishLaunchingWithOptions method

UINavigationController *navController = [[UINavigationController alloc] init];
self.window.rootViewController = navController;

SubClass *viewController1 = [[[SubClass alloc] initWithNibName:@"SubClass" bundle:nil] autorelease];

[navController pushViewController:viewController1 animated:YES];

SuperClass.h

#import <UIKit/UIKit.h>

@interface SuperClass : UIViewController
@end

SuperClass.m

#import <UIKit/UIKit.h>
#import "SuperClass.h"

@implementation SuperClass
@end

SubClass.h

#import <UIKit/UIKit.h>
#import "SuperClass.h"

@interface SubClass : SuperClass
@end

SubClass.m

#import <UIKit/UIKit.h>
#import "SubClass.h"

@implementation SubClass

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
    }
    return self;
}

- (void)viewDidLoad
{
    NSLog(@"Methods %@ called", NSStringFromSelector(_cmd));
    [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
}
@end

This works for me, make sure you set the right class for your nibFile aswell. Click on the file's owner icon and change the class from UIViewController to SubClass

Upvotes: 0

jrturton
jrturton

Reputation: 119242

You say you are creating views in code (using loadView) in the super class, but trying to use a nib in the sub class?

According to the UIViewController docs (emphasis mine)

If you specify views using a nib file, you must not override loadView but should instead create a nib file in Interface Builder...

It looks like you may have a conflict there. As a test, comment out the loadView method in your superclass and see where that gets you.

Upvotes: 2

Related Questions