为什么我的superview-with-subview在以模态方式呈现时会缩小(使用自动布局)?

时间:2013-05-28 13:54:41

标签: ios autolayout

我有一个拥有单个自定义视图的视图控制器;自定义视图使用Core Graphics绘制游戏板。 (不涉及其他子视图。)

我设置了自动布局约束,以便游戏板填充其超级视图。当我将视图控制器设置为根视图控制器时,游戏板(和superview)填充屏幕,这是我的意图。但是,当我以模态方式呈现视图控制器时,游戏板(和superview)缩小到空/最小,并且自动布局跟踪报告布局不明确。

我写了一个简化的测试用例来说明这个问题。

这是我的BoardViewController,其顶层视图带有绿色背景,但会创建一个带红色背景的单个扩展子视图。当这个视图控制器接管时,我想看到屏幕都是红色的:

- (void)loadView
{
  UIView *mainView = [[UIView alloc] init];
  mainView.translatesAutoresizingMaskIntoConstraints = NO;
  mainView.backgroundColor = [UIColor greenColor];

  UIView *subView = [[UIView alloc] init];
  subView.translatesAutoresizingMaskIntoConstraints = NO;
  subView.backgroundColor = [UIColor redColor];

  [mainView addSubview:subView];
  self.view = mainView;

  NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(subView);
  NSArray *c1 = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[subView(>=10)]|"
                                                        options:0
                                                        metrics:nil
                                                          views:viewsDictionary];
  NSArray *c2 = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[subView(>=10)]|"
                                                        options:0
                                                        metrics:nil
                                                          views:viewsDictionary];
  [self.view addConstraints:c1];
  [self.view addConstraints:c2];
}

如果我将它设置为我的根视图控制器,那么我会看到我漂亮的红色游戏板填满了屏幕。但是,当我从另一个BoardViewController展示RootViewController时,游戏板缩小到最小10x10平方:

- (void)loadView
{
  UIView *rootView = [[UIView alloc] init];
  rootView.translatesAutoresizingMaskIntoConstraints = NO;

  UIButton *presentButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
  presentButton.translatesAutoresizingMaskIntoConstraints = NO;
  [presentButton setTitle:@"Present" forState:UIControlStateNormal];
  [presentButton addTarget:self
                    action:@selector(present:)
          forControlEvents:UIControlEventTouchUpInside];

  [rootView addSubview:presentButton];
  self.view = rootView;

  [rootView addConstraint:[NSLayoutConstraint constraintWithItem:presentButton
                                                       attribute:NSLayoutAttributeCenterX
                                                       relatedBy:NSLayoutRelationEqual
                                                          toItem:rootView
                                                       attribute:NSLayoutAttributeCenterX
                                                      multiplier:1.0
                                                        constant:0.0]];
  [rootView addConstraint:[NSLayoutConstraint constraintWithItem:presentButton
                                                       attribute:NSLayoutAttributeCenterY
                                                       relatedBy:NSLayoutRelationEqual
                                                          toItem:rootView
                                                          attribute:NSLayoutAttributeCenterY
                                                      multiplier:1.0
                                                      constant:0.0]];
}

- (void)present:(id)sender
{
  BoardViewController *bvc = [[BoardViewController alloc] init];
  [self presentViewController:bvc animated:YES completion:NULL];
}

我一直在尝试不同的自动布局规则,但无论我做什么,当视图控制器以模态方式呈现时,我无法让游戏板填满屏幕。 (与此同时我问这个问题,我试图让运行时告诉我它的想法是不明确的。但是我的调试还不是很好,因此我的问题在这里。)

2 个答案:

答案 0 :(得分:3)

经过一些调查后,看起来当您按下模态视图控制器全屏时,动画完成后,将从视图层次结构中删除呈现视图控制器及其视图。正如预期的那样,视图约束正被删除。一旦关闭模态视图控制器,原始视图控制器及其视图将再次返回,但约束已消失,系统尚未保存和恢复。那是一个错误。甚至在iOS7上。 使用NSAutoresizingConstraints的原因是,视图系统能够自行重建约束。

作为旁注:如果您使用嵌套的viewControllers进行设置(例如外部视图控制器嵌入导航控制器),则可以使用子视图控制器模式链接这些设置。如果您已经这样做了,最上面的viewController视图将被我上面描述的删除。这意味着您必须仅将NSAutoresizingConstraints补丁应用于最顶层的viewcontroller(通常是windows根视图控制器),并在其间使用标准约束。

答案 1 :(得分:2)

卸下:

mainView.translatesAutoresizingMaskIntoConstraints = NO;

这很有意思。这意味着当使用presentViewController以模态方式呈现视图时,预计会将其与超级视图相关联,但是当设置为rootViewController的{​​{1}}时,它不需要它们。 ..