为啥我的 superview-with-subview 在模态显示(使用自动布局)时会缩小?

Posted

技术标签:

【中文标题】为啥我的 superview-with-subview 在模态显示(使用自动布局)时会缩小?【英文标题】:Why does my superview-with-subview shrink when presented modally (using Auto Layout)?为什么我的 superview-with-subview 在模态显示(使用自动布局)时会缩小? 【发布时间】:2013-05-28 13:54:40 【问题描述】:

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

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

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

这是我的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];

如果我将它设置为我的根视图控制器,那么我会看到我漂亮的红色游戏板填满了屏幕。但是,当我从另一个 RootViewController 中展示 BoardViewController 时,游戏板会缩小到最小 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];

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

【问题讨论】:

【参考方案1】:

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

附带说明:如果您有嵌套视图控制器的设置(例如,外部视图控制器嵌入导航控制器),那么您可以使用子视图控制器模式链接它们。如果你这样做了,最上面的 viewController 视图将被我上面描述的内容删除。这意味着您必须只将 NSAutoresizingConstraints 补丁应用于最顶层的视图控制器(通常是 Windows 根视图控制器),并在其间使用标准约束。

【讨论】:

【参考方案2】:

删除:

mainView.translatesAutoresizingMaskIntoConstraints = NO;

这很有趣。这意味着当使用presentViewController 以模态方式呈现视图时,它应该具有与其父视图相关的约束,但是当设置为UIWindowrootViewController 时,它不需要它们...

【讨论】:

太棒了!谢谢!所以,解释:我错误地弄乱了我的***视图的布局,这是任何人向我展示的权限。在这种情况下,presentViewController:animate:completion:(我们假设)使用 springs-and-struts 添加它的视图,所以我打破了它。这是一种公平的表述方式吗? 据我所见,rootViewController 的窗口似乎是一种绕过约束的特殊情况。如果您离开 mainView.translatesAutoresizingMaskIntoConstraints = NO; 并实施 updateConstraints 以手动添加一些约束,那么尝试一下会发生什么会很有趣...... 我尝试将 [self.view translatesAutoresizingMaskIntoConstraints] 的值转储到 viewDidAppear: 以用于模态演示和被设置为根视图控制器。在这两种情况下,它都抛弃了YES。也许将视图设置为根视图控制器会显式设置其框架,而呈现视图控制器则不会。

以上是关于为啥我的 superview-with-subview 在模态显示(使用自动布局)时会缩小?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的 PHP 会话会死掉?为啥我不能恢复它们?

为啥我的碰撞测试总是返回“真”,为啥图像矩形的位置总是错误的 (0, 0)?

NPM 启动错误上的 ENOENT。为啥我会收到此错误,为啥要查找“我的图片”目录?

为啥 main 前面有一个 int ,为啥我的教授会排除它? [复制]

为啥我的 Entity Framework Code First 代理集合为空,为啥我不能设置它?

为啥我的 UISearchController 很慢?