viewDidLoad никогда не вызывался в подклассе UIViewController
У меня возникли проблемы с загрузкой субклассированного UIViewController из пера. Моя функция viewDidLoad никогда не вызывается.
У суперкласса нет пера, но у подклассов есть свои. т.е.
@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
}
Вид загружается из пера следующим образом:
SubClass *scvc = [[SubClass alloc] initWithNibName:@"SubClass" bundle:nil];
[self.navigationController pushViewController:scvc animated:YES];
[scvc release];
Существует файл пера с этим именем, и у него правильно установлен класс владельца файла.
viewDidLoad не вызывается у ребенка или супер. Есть идеи?
4 ответа
Вы говорите, что создаете представления в коде (используя loadView) в суперклассе, но пытаетесь использовать кончик в подклассе?
Согласно документам UIViewController (выделено мое)
Если вы задаете представления с помощью файла пера, вы не должны переопределять loadView, а должны вместо этого создать файл пера в Интерфейсном Разработчике...
Похоже, у вас там может быть конфликт. В качестве теста закомментируйте метод loadView в своем суперклассе и посмотрите, куда вас это приведет.
Я предполагаю, что SuperClass реализует loadView. Поэтому, когда ваш подкласс запрашивает loadView, вы получаете реализацию своего суперкласса, которая переопределяет обычный механизм загрузки пера.
Я бы переосмыслил ваш дизайн здесь. Поведение вашего суперкласса сильно отличается от того, что вы хотите, чтобы ваш подкласс делал. Может быть, это не лучшие отношения там.
Но, если вы хотите, вы должны быть в состоянии, по крайней мере, заставить его работать, выполнив это в вашем SubClass.m:
-(void)loadView {
IMP defaultImp = class_getMethodImplementation([[self superclass] superclass], _cmd);
/* or alternatively...
IMP defaultImp = class_getMethodImplementation([UIViewController class], _cmd);
*/
defaultImp(self, _cmd);
}
Это реализует loadView для вашего подкласса, который пропускает loadView вашего SuperClass и вместо этого вызывает реализацию по умолчанию.
IMO, это уродливо и, возможно, потребуется пересмотреть, если ваша иерархия классов расширилась. Я бы не стал делать это в своем собственном приложении, вместо этого я бы переосмыслил иерархию классов.
Где находится этот блок
SubClass *scvc = [[SubClass alloc] initWithNibName:@"SubClass" bundle:nil];
[self.navigationController pushViewController:scvc animated:YES];
[scvc release];
Вы уверены, что это называется?
Я сделал тест-проект, чтобы проверить его, и следующие работы:
В вашем файле appDelegate.m я поместил следующее в метод didFinishLaunchingWithOptions приложения
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
Это работает для меня, убедитесь, что вы правильно установили класс для своего nibFile. Нажмите на значок владельца файла и измените класс с UIViewController на SubClass