Reputation: 31
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
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
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
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