弹出UIViewController会导致先前的UIViewControllers视图更改位置

时间:2015-06-13 12:32:39

标签: ios uinavigationcontroller

我有一个UINavigationController,其UIViewController设置为它的rootController,它在其UIView上使用navBar下的图像集包含背景。然后我向导航控制器推送一个新的UIViewController,当按下后退按钮时,前一个控制器看起来不同。使用可视化调试器,我可以看到self.view完全向下移动到navBar之下,而navBar之前位于顶部。我不知道并且为了这可能发生的原因而绞尽脑汁 Before Navigation stack Push

enter image description here

-(void)pushIPhoneMessagingContactsController:(MessageContactsViewController *)contactsController{
    self.selectorView.hidden = YES;
    [self.navigationController pushViewController:contactsController animated:YES];
}

在RootViewController(iPhoneMessagingNotificationsController)

-(void)viewWillAppear:(BOOL)animated{
    self.selectorView.hidden = NO;
    [[[self navigationItem] leftBarButtonItem] setTintColor:[UIColor blackColor]];
    [[UIApplication sharedApplication]      setStatusBarStyle:UIStatusBarStyleDefault];

    if ([_displayType intValue] == MESSAGES_SHOWING) {
        [self.notificationsViewController.view removeFromSuperview];
        [self.contentView addSubview:_messagesViewController.view];
    } else {
        [self.messagesViewController.view removeFromSuperview];
        [self.contentView addSubview:_notificationsViewController.view];
    }

}

2 个答案:

答案 0 :(得分:2)

似乎违规行在推送的UIViewController的viewWillAppear方法中

self.navigationController.navigationBar.translucent = YES;

其他地方此navigationBar设置为半透明:

 [self.navigationController.navigationBar setBackgroundImage:[UIImage new]
                                              forBarMetrics:UIBarMetricsDefault];
 self.navigationController.navigationBar.shadowImage = [UIImage new];
 self.navigationController.navigationBar.translucent = YES;

再次使它成为纯色:

 self.navigationController.navigationBar.shadowImage = nil;
 self.navigationController.navigationBar.translucent = NO;

但是这段代码似乎搞乱了布局,所以也许还有另一种方法来改变navBar和statusBar的不透明度而不影响布局?

答案 1 :(得分:1)

您当前正在尝试隐藏或显示的selectorView实际上只应针对一个特定的视图控制器显示。

这是解决此问题的封装方式,使您的selectorView成为根视图控制器的一部分,从其他视图控制器中删除连接。他们不再需要知道或隐藏它。

将您的selectorView添加到rootViewController的导航栏titleView。 (您可以在代码中执行此操作,或将其放在Storyboard中并为其添加IBOutlet。)

self.navigationItem.titleView = selectorView;

现在,当您推送另一个视图控制器时,其标题将替换您的rootViewController的selectorView标题(视图)。您的其他视图控制器不需要了解该视图的任何信息。

这是一种很好的设计方法。只要您的控件只出现在一个视图控制器的导航栏上,您就希望它成为该视图控制器的navigationItem(titleView或左/右栏按钮项目)的一部分。)iOS将在显示视图控制器时显示控件,并在该视图控制器不再是导航控制器堆栈中的顶视图控制器时隐藏控件。

对于64像素高度问题,它可能与rootViewController层次结构中的某些复杂性有关,而这种复杂性不应该存在。

在iOS 7/8中,视图的内容默认显示在半透明导航栏下。 Apple通过插入视图层次结构的第一个视图,为您自由管理这个。

从您的代码中,您似乎正在尝试隐藏"或"显示" (un)选择了viewController的视图。

每个视图控制器都应该有一个它控制的视图。视图控制器不应该尝试控制其他视图控制器的视图,或者将其他视图控制器的视图添加到其自己的视图层次结构中

这是Apple推荐的解决方法。在rootViewController中使用containerView。容器视图的整个目的是将视图控制器封装在视图中。当您的selectorView更改要显示的视图时,您的容器视图会从一个视图控制器转换到另一个视图控制器。 (如果您不熟悉如何操作,请查看此answer。)

将containerView固定到rootViewController的视图,因此Auto Layout可以为您调整大小。

您的视图层次结构现在看起来像视图 - > containerView,而不是view - >未选择的视图控制器的隐藏视图,所选视图控制器的显示视图。 Apple可以调整第一个视图的插图,没有任何错误偏移(通过导航控件的高度)。

<强>更新

question讨论scrollViewInsets以及如何在逐个控制器的视图控制器基础上设置它们。如果您有视图控制器,并且不希望其内容显示在条形图下,请取消选中该框。

但处理这个问题的最佳方法是&#34;标准化&#34;您的用户界面,因此从视图到视图都不一样。要么使酒吧总是半透明,要么不总是半透明。这使得转换更少&#34;震动&#34;为用户。