【问题标题】:SplitViewController Woes - replacing detail view controller in portrait mode failureSplitViewController Woes - 在纵向模式下替换细节视图控制器失败
【发布时间】:2012-08-12 01:40:17
【问题描述】:

我有一个运行良好的 SVC 设置。 SPC 的主视图和详细视图都是 UINavigationController,每个都有单独的根视图控制器。

我的应用程序运行良好。我可以在纵向或横向模式下启动它,一切正常。 “主”弹出按钮在纵向模式下可见,但在横向模式下隐藏。主平面和细节平面都正确设置动画和旋转,不存在弹出或奇怪的动画伪影,并且一切都正确拉伸。每个规格 100% 的满意度。

当我更换细节视图控制器时出现问题。由于我们无法替换 uinavi 控制器的根节点,我要做的是创建一个全新的UINavigationController,并在详细视图中为其分配我想要的新视图。我这样做是因为详细视图中的视图可以做 1-2-3 级深度,但我需要能够分配唯一的“根”视图(例如,我需要能够完全替换根 UINavigationController)。

代码如下所示:

self.detailViewController = [[SomeNewController1of3 alloc] initWithNibName:@"SomeNewController1of3" bundle:nil];
self.splitViewController.delegate = self.detailViewController;
UINavigationController *newNC = [[UINavigationController alloc] initWithRootViewController:self.detailViewController];
self.splitViewController.viewControllers = @[navigationController, newN];

首先,我创建新的视图控制器,不管它是什么。然后我将 splitviewcontroller 的委托设置为 = 新创建的 viewcontroller(以便willHideViewController 等触发)。然后我创建了一个导航控制器来容纳新创建的视图控制器,以便它可以从中推送和弹出。最后,我用我的新导航控制器替换了拆分视图控制器的第二个(详细)视图。

同样,当我从横向开始时,这个计划完美无缺。

当我从纵向开始时,我注意到以下异常情况:

  1. 所有弹出窗口(警报框、主视图等)都有奇怪的旋转,并且在显示时会从一个尴尬的位置弹出。就好像它在这些弹出窗口显示时立即旋转它们,而不是让它们简单地“滑出”正确的位置。
  2. 当显示主视图时,在进行上述奇怪的旋转后,它会瞬间完全消失(留下一个黑色的空白区域),然后恢复到原来的位置。
  3. 在我完成设备旋转之前,不会显示详细视图控制器上显示主视图弹出窗口的“主”按钮。确认断点后,我确实得出结论,willHideViewController 没有被我的上述方法调用。

我不明白为什么当我从横向开始时一切都表现得完美无缺,但所有这些错误都出现在纵向?我所有的视图实际上在 IB 中都有一个默认方向设置为纵向,并且可以缩放以适应。此外,它们不像是疯狂的界面,它们都只是普通的 tableviews。

你们有没有遇到过这个问题或找到解决它的方法?

【问题讨论】:

  • 为什么说“我们不能替换uinavi控制器的根节点”?您可以使用setViewControllers:animated: 设置新的视图控制器堆栈(包括根视图控制器)。
  • 所以我继续并更改了我的代码,这样它就不会创建一个新的细节(ui nav 控制器),而是抓住现有的细节。然后按照上面评论中的说明设置 viewControllers 数组。这是朝着正确方向迈出的一步(更简单的代码),但是我注意到的所有 3 个异常仍然会发生——同样,只有当应用程序以纵向模式启动时。

标签: iphone ios orientation uisplitviewcontroller


【解决方案1】:

首先,UISplitViewController 委托应该是像您的 App Delegate 这样的顶级对象,而不是拆分控制器显示的视图控制器。

其次,要回答您的问题,要以纵向替换显示详细视图控制器(即推送到主导航上),您可以使用拆分控制器委托方法:

AppDelegate.m

- (BOOL)splitViewController:(UISplitViewController *)splitViewController showDetailViewController:(UIViewController *)vc sender:(id)sender{
    if(!splitViewController.isCollapsed){
        return NO;
    }
    UINavigationController *masterNav = splitViewController.viewControllers.firstObject;
    if(![masterNav.topViewController isKindOfClass:UINavigationController.class]){
        return NO;
    }
    UINavigationController *existingDetailNav = (UINavigationController *)masterNav.topViewController;
    UINavigationController *newDetailNav = (UINavigationController *)vc;
    existingDetailNav.viewControllers = @[newDetailNav.viewControllers.firstObject];
    return YES;
}

您可能想知道为什么我们不只是替换主导航堆栈。问题是拆分视图控制器保留了上次 showDetail 经历其默认行为的细节视图控制器。因此,如果我们是纵向的,点击一个单元格以显示细节,然后替换细节,然后导航回来,然后在旋转到横向时,旧的细节将显示在右侧,而不是新的细节。通过用上面的新细节控制器替换细节导航堆栈,这解决了这个问题,因为尽管拆分显示了保留的细节导航,但它现在包含新的细节。

【讨论】:

  • bruh,我在 7 年前问过这个问题。我什至不知道objective-c了
  • 这是一个很好的问题,远远领先于时代。你现在在做什么?
【解决方案2】:

我发现子类化 SplitViewController 更容易。从那里,您可以轻松地为需要它的人更换添加 navController 的细节。

子类 UISplitViewController 并将您的根 splitViewController 设置为该类。然后将此方法添加到您的 UISplitViewController 子类中:

-(void)setDetailControllerTo:(UIViewController *)detailController withNavControllerTitle:(NSString *)title {
[detailController view]; // this line forces the viewDidLoad method to be called

if (title) {
    UINavigationController *navController = [[UINavigationController alloc] init];
    [navController pushViewController:detailController animated:YES];
    detailController.title = title;

    NSArray *viewControllers=@[self.mainController.viewControllers[0],navController];
    self.mainController.viewControllers = viewControllers;
} else {
    NSArray *viewControllers=@[self.mainController.viewControllers[0],detailController];
    self.mainController.viewControllers = viewControllers;
}

}

要调用此方法,请从 tableView:didSelectRowAtIndexPath: 方法中的主视图控制器执行类似的操作

FixedSplitViewController *splitController = (FixedSplitViewController*) self.splitViewController;

CurrentEventViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:@"CurrentEventViewController"];
// add any setup code here
[splitController setDetailControllerTo:controller withNavControllerTitle:@"Current Event"];

如果您希望在纵向旋转中保持主视图可见,请将此方法添加到 SplitViewController 子类:

-(BOOL)splitViewController:(UISplitViewController *)svc shouldHideViewController:(UIViewController *)vc inOrientation:(UIInterfaceOrientation)orientation {
    return NO;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多