ViewWillAppear не вызывается с помощью UISplitViewController - PullRequest
7 голосов
/ 25 октября 2011

Справочная информация и цель: у меня есть приложение для iPad на основе UISplitViewController - до сих пор оно поддерживало 4 ориентации, но теперь я хочу ограничить его только пейзажем. Я изменил shouldAutorotateToInterfaceOrientation левого контроллера вида, чтобы он поддерживал только альбомный режим, но это мешает viewWillAppear вызываться.

Детали: контроллеры представления моего iPad организованы следующим образом:

window
`-- splitVC (UISplitViewController)
    `-- rootNav (UINavigationController)
        `-- hvc (HostManagerViewController, derived from UIViewController)
    `-- detailViewController (DetailViewController, derived from UIViewController)

Это реализовано в делегате приложения, как показано ниже:

- (BOOL)application:(UIApplication *)application
         didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    HostManagerViewController *hvc  = [[[HostManagerViewController alloc]
                                       initWithNibName:nil bundle:nil] autorelease];
    self.detailViewController = [[[DetailViewController alloc]
                                initWithNibName:nil bundle:nil] autorelease];
    UINavigationController *rootNav = [[[UINavigationController alloc]
                                        initWithRootViewController:hvc] autorelease];
    UISplitViewController *splitVC= [[[UISplitViewController alloc] init] autorelease];
    [splitVC setViewControllers:[NSArray arrayWithObjects:rootNav,
                                 detailViewController, nil]];

    splitVC.delegate = detailViewController;
    [window addSubview:splitVC.view];
    [window setRootViewController:splitVC];
    return YES;
}

viewWillAppear вызывается, когда оба DetailViewController.m и HostManagerViewController.m содержат

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    return YES;
}
Console output:
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 3
Hostmanager: Viewdidload
Should rotate called to hostmanager with 1
Hostmanager: viewwillappear

Но когда я меняю код HostManagerViewController на

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    return (UIInterfaceOrientationIsLandscape(interfaceOrientation));
}

тогда 'viewWillAppear` HostManagerViewController не вызывается. Консольный вывод

Should rotate called to hostmanager with 1 (1 is the numeric value of interfaceOrientation)
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 3
Should rotate called to hostmanager with 3
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 3
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 3
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 1
Should rotate called to hostmanager with 3
Hostmanager: Viewdidload
Should rotate called to hostmanager with 1

В Info.plist поддерживаются только ландшафтные режимы

EDIT: вставлены сообщения NSLog для отслеживания shouldAutorotateToInterfaceOrientation, viewWillAppear и ViewDidLoad

Ответы [ 3 ]

8 голосов
/ 18 ноября 2011

Я спросил, какую версию iOS вы используете, потому что я пытался создать простое воспроизведение вашей проблемы и обнаружил, что поведение отличается между 4.3 и 5.0. Это действительно делает все правильные звонки в 5.0. Я считаю, что это просто ошибка с UISplitviewController. Контроллер Splitview был довольно глючным. Ответ Aopsfan не решает проблему (я подтвердил это). Я бы предложил создать подклассы контроллера uisplitview и переопределить viewwillappear контроллера splitview, viewdid появиться так:

#import "testSplitViewController.h"

@implementation testSplitViewController

-(void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    NSString *reqSysVer = @"5.0";
    NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
    if ([currSysVer compare:reqSysVer options:NSNumericSearch] == NSOrderedAscending)
        [[[self viewControllers] objectAtIndex:0] viewWillAppear:animated];
}

-(void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];

    NSString *reqSysVer = @"5.0";
    NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
    if ([currSysVer compare:reqSysVer options:NSNumericSearch] == NSOrderedAscending)
        [[[self viewControllers] objectAtIndex:0] viewDidAppear:animated];
}
@end

Вы должны проверить номер версии, чтобы дважды не вызывать viewDidAppear.

Или просто используйте 5.0 или выше, если можете, так как ошибка кажется исправленной.

3 голосов
/ 17 ноября 2011

По сути, поскольку UISplitViewController состоит из двух частей, вам необходима универсальная реализация shouldAutorotate.Я предполагаю, что решение проблемы поворота контроллеров представления по отдельности может вызвать некоторые странные побочные эффекты - хотя, пожалуйста, обратите внимание, что я не смог воспроизвести вашу проблему viewWillAppear, так что это решение действительно является предположением.

Я бы порекомендовал сделать простейший подкласс UISplitViewController.Назовите его «SplitViewController», и в его .m файле удалите все, кроме shouldAutorotate, которое будет выглядеть следующим образом:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    return (UIInterfaceOrientationIsLandscape(interfaceOrientation));
}

Теперь измените свой код shouldAutorotate в HostManagerViewController и DetailViewController обратно на:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    return YES;
}

Теперь в вашем делегате приложения используйте этот класс вместо UISplitViewController.Это должно (может) решить вашу проблему.

0 голосов
/ 17 ноября 2011

Вы устанавливаете делегата UISplitViewControler на detailViewController

splitVC.delegate = detailViewController;

Я думаю, что лучшее место для блокировки поворотов будет в DetailViewController, а не в HostManagerViewController.Я бы изменил - shouldAutorotateToInterfaceOrientation в HostManagerViewController, чтобы он всегда возвращал YES, а в DetailViewController я бы добавил:

-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (UIInterfaceOrientationIsLandscape == interfaceOrientation);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...