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

Попробуйте добавить:

[super viewDidLoad];
Другие вопросы по тегам