【问题标题】:ViewWillAppear not getting called with UISplitViewControllerViewWillAppear 没有被 UISplitViewController 调用
【发布时间】:2011-10-25 13:55:48
【问题描述】:

背景和目标:我有一个基于 UISplitViewController 的 iPad 应用程序 - 到目前为止它支持 4 个方向,但现在我想将其锁定为仅横向。 我将左视图控制器的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 消息以跟踪 shouldAutorotateToInterfaceOrientationviewWillAppearViewDidLoad

【问题讨论】:

  • 您可以上传这个项目的样本吗?
  • 你在哪个 iOS 版本上运行这个?
  • 我使用的是 4.3。可以将其缩减为更小的测试用例。那我在哪里上传呢?
  • 您尝试过我帖子中的建议吗?很有可能会解决您的问题。您正在将 SplitViewController 委托设置为 detailviewcontroller,如果这将为更改方向返回 YES,那么它将尝试旋转位于 SplitViewController 内的所有控制器,然后您的 HostManagerViewController 将拒绝更改方向(这可能是您的问题) .

标签: objective-c ios ipad


【解决方案1】:

我问您使用的是哪个 iOS 版本,因为我试图创建一个简单的重现您的问题的方法,但发现 4.3 和 5.0 的行为有所不同。它实际上确实在 5.0 中进行了所有正确的调用。我相信这只是 UISplitviewController 的一个错误。 Splitview 控制器非常有问题。 aopsfan 的回答并没有解决问题(我已经确认了这一点)。我建议继承 uisplitviewcontroller,并覆盖 splitview 控制器的 viewwillappear、viewdidappear,如下所示:

#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 或更高版本,因为该错误似乎已修复。

【讨论】:

  • 是的,是的,是的!拆分视图控制器中似乎存在错误 - 因此从拆分视图强制 viewWillAppear 对子视图似乎是解决方法。非常感谢,@ACBurk
  • 在调用viewDidAppear 之前,有没有比版本检查更通用的方法?有isViewLoaded,但也有hasViewAppeared 之类的电话吗?
  • 我不知道,但我会调查一下
  • 这可能是一个比 UISplitViewController 更普遍的问题。我遇到了在 iOS-4 iPad 上的普通视图控制器上不调用 viewDidAppear: (和 viewWillAppear:) 的情况,但在 iOS-5 iPad 上运行时会调用这些方法。
  • 而且我似乎有一个问题,它甚至在 iPad 上的 iOS5 上都没有被调用。去图吧。
【解决方案2】:

基本上,由于UISplitViewController 有两个部分,因此您需要一个通用的 shouldAutorotate 实现。我想单独处理视图控制器的旋转会导致一些奇怪的副作用——尽管请注意我无法复制你的viewWillAppear 问题,所以这个解决方案确实是一个猜测。

我建议创建一个非常简单的UISplitViewController 子类。将其命名为“SplitViewController”,在它的.m 文件中,删除除 shouldAutorotate 之外的所有内容,如下所示:

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

现在将 HostManagerViewControllerDetailViewController 中的 shouldAutorotate 代码改回:

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

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

【讨论】:

  • 我也同意 aopsfan,你不应该在每个视图控制器上阻止它,你应该在根控制器中阻止它(在你的情况下是 UISplitViewController)。
  • +1 感谢您提出此建议。不幸的是,它并没有解决问题
【解决方案3】:

您将 UISplitViewControler 的委托设置为 detailViewController

splitVC.delegate = detailViewController;

我认为阻止旋转的最佳位置是在 DetailViewController 中,而不是在 HostManagerViewController 中。我将更改 HostManagerViewController 中的 - shouldAutorotateToInterfaceOrientation 以始终返回 YES 并在 DetailViewController 中添加:

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

【讨论】:

    猜你喜欢
    • 2016-03-24
    • 2011-05-19
    • 2011-04-03
    • 1970-01-01
    • 1970-01-01
    • 2010-10-28
    • 2012-06-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多