ViewWillAppear没有被UISplitViewController调用

背景和目标:我有一个UISplitViewController基于iPad的应用程序 – 直到现在它支持4个方向,但现在我想locking它只有风景。 我改变左视图控制器的shouldAutorotateToInterfaceOrientation只支持横向模式,但是这停止了它的viewWillAppear被调用。

详细信息:我的iPad的视图控制器组织如下:

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

这是在App Delegate中实现的,如下所示:

 - (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; } 

DetailViewController.mHostManagerViewController.m都包含时, viewWillAppear被调用

 - (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)); } 

那么HostManagerViewController的“viewWillAppear”不会被调用。 控制台输出

 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中只支持横向模式

编辑:插入NSLog消息跟踪ViewDidLoadviewWillAppearViewDidLoad

我问你使用的是什么版本的iOS,因为我试图创build一个简单的问题复制,发现4.3和5.0之间的行为不同。 它实际上确实在5.0中进行了所有正确的调用。 我相信这只是与UISplitviewController的一个错误。 Splitview控制器相当麻烦。 aopsfan的回答没有解决问题(我已经证实了这一点)。 我build议子类化uisplitviewcontroller,并重写splitview控制器的viewwillappear,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或​​更高,因为这个bug似乎是固定的。

基本上,因为一个UISplitViewController有两个部分,所以你需要一个通用的UISplitViewController实现。 我认为,单独处理视图控制器的旋转可能会导致一些奇怪的副作用 – 尽pipe请注意,我无法复制viewWillAppear问题,所以这个解决scheme真的是一个猜测。

我会build议做一个UISplitViewController的死简单的子类。 将其命名为“SplitViewController”,并将其命名为.m文件,删除除了shouldAutorotate之外的所有内容,如下所示:

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

现在在HostManagerViewControllerDetailViewController HostManagerViewController您的HostManagerViewController代码改回到:

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

现在,在您的应用程序委托中,使用此类而不是UISplitViewController 。 这应该(可能)解决您的问题。

您将UISplitViewControler的委托设置为detailViewController

 splitVC.delegate = detailViewController; 

我认为阻止旋转的最佳位置将在DetailViewController中,而不是在HostManagerViewController中。 我会更改HostManagerViewController中的 – shouldAutorotateToInterfaceOrientation返回allways是,并在DetailViewController我会添加:

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