UIAlertView/Controller 的自动布局错误?

Autolayout bug with UIAlertView/Controller?

我正在尝试为每个方向切换我的项目的自动布局约束,并通过以编程方式删除和添加 NSAutoLayoutConstraints 的纵向和横向集来实现。对于两个方向的布局,我都有正确的自动布局约束(我认为)。我的故事板 不是 使用大小 类 以实现兼容性。

我已经截取了正确布局的屏幕截图。红色部分是 UI 红色视图。

纵向布局

横向布局

我的 viewWillLayoutSubviews: 是

- (void)viewWillLayoutSubviews {
    [self.termToolbar invalidateIntrinsicContentSize];
}

并且添加和删除的所有约束都在 updateViewConstraints

以纵向启动应用程序然后旋转到横向时,出现约束错误:

2015-07-26 10:50:42.856 reproduce[1084:23311] Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
    "<_UILayoutSupportConstraint:0x786436c0 V:[_UILayoutGuide:0x7864cb70(20)]>",
    "<_UILayoutSupportConstraint:0x78643680 V:|-(0)-[_UILayoutGuide:0x7864cb70]   (Names: '|':UIView:0x7864ca90 )>",
    "<NSLayoutConstraint:0x78657bc0 'UIView-Encapsulated-Layout-Width' H:[UIView:0x7864ca90(480)]>",
    "<NSLayoutConstraint:0x78657bf0 'UIView-Encapsulated-Layout-Height' V:[UIView:0x7864ca90(320)]>",
    "<NSLayoutConstraint:0x786593c0 V:[_UILayoutGuide:0x7864cb70]-(0)-[UISearchBar:0x78a21a70]>",
    "<NSLayoutConstraint:0x786593f0 V:[UISearchBar:0x78a21a70]-(0)-[UITableView:0x7982aa00]>",
    "<NSLayoutConstraint:0x78659420 V:[UITableView:0x7982aa00]-(0)-[UIView:0x78a216f0]>",
    "<NSLayoutConstraint:0x78620570 V:[UIView:0x78a216f0]-(0)-[UIToolbar:0x78b81d00]>",
    "<NSLayoutConstraint:0x786205a0 V:[UIToolbar:0x78b81d00]-(0)-|   (Names: '|':UIView:0x7864ca90 )>",
    "<NSLayoutConstraint:0x786590a0 UIView:0x78a216f0.height == 0.75*UIView:0x78a216f0.width>",
    "<NSLayoutConstraint:0x786596d0 H:|-(0)-[UIView:0x78a216f0]   (Names: '|':UIView:0x7864ca90 )>",
    "<NSLayoutConstraint:0x78659720 H:[UIView:0x78a216f0]-(0)-|   (Names: '|':UIView:0x7864ca90 )>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x786593f0 V:[UISearchBar:0x78a21a70]-(0)-[UITableView:0x7982aa00]>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.

请注意,我正在从纵向旋转到横向,显示的错误是针对纵向方向!从横向旋转到纵向时,不会发生调试 output/error。旋转回横向会导致相同的错误。

即使有这些错误,在我显示 UIAlertView/Controller 之前,视图布局对于纵向和横向都显示良好。一旦显示警报,布局就会失败, 纵向和横向布局都显示错误(UITableView 消失,红色 UIView 占据整个屏幕,等等). 如果警报被解除或仍在显示 都没有关系,每次警报后布局都会失败。

我创建了一个示例项目来重现可以找到的这种行为 here。 UI 元素出口在 IB 中连接。所有代码都在默认的ViewControllerclass。知道为什么会发生这种行为,或者这是 AutoLayout 中用于在方向之间进行简单布局更改的错误?谢谢。

纵向限制:

<NSLayoutConstraint:0x7b05cda0 V:|-(0)-[_UILayoutGuide:0x7b0648a0]   (Names: '|':UIView:0x7b064990 )>,
<NSLayoutConstraint:0x7b05cc30 V:[_UILayoutGuide:0x7b0648a0]-(0)-[UISearchBar:0x7b0e9590]>,
<NSLayoutConstraint:0x7b05cc00 V:[UISearchBar:0x7b0e9590]-(0)-[UITableView:0x7cb4d600]>,
<NSLayoutConstraint:0x7b05cbd0 V:[UITableView:0x7cb4d600]-(0)-[UIView:0x7b0e9210]>,
<NSLayoutConstraint:0x7b05cba0 V:[UIView:0x7b0e9210]-(0)-[UIToolbar:0x7b069f10]>,
<NSLayoutConstraint:0x7b05cb70 V:[UIToolbar:0x7b069f10]-(0)-|   (Names: '|':UIView:0x7b064990 )>,
<NSLayoutConstraint:0x7b05ced0 UIView:0x7b0e9210.height == 0.75*UIView:0x7b0e9210.width>,
<NSLayoutConstraint:0x7b05c990 H:|-(0)-[UISearchBar:0x7b0e9590]   (Names: '|':UIView:0x7b064990 )>,
<NSLayoutConstraint:0x7b05c940 H:[UISearchBar:0x7b0e9590]-(0)-|   (Names: '|':UIView:0x7b064990 )>,
<NSLayoutConstraint:0x7b05c8a0 H:|-(0)-[UIView:0x7b0e9210]   (Names: '|':UIView:0x7b064990 )>,
<NSLayoutConstraint:0x7b05c850 H:[UIView:0x7b0e9210]-(0)-|   (Names: '|':UIView:0x7b064990 )>,
<NSLayoutConstraint:0x7b05c780 H:|-(0)-[UITableView:0x7cb4d600]   (Names: '|':UIView:0x7b064990 )>,
<NSLayoutConstraint:0x7b05c730 H:[UITableView:0x7cb4d600]-(0)-|   (Names: '|':UIView:0x7b064990 )>,
<NSLayoutConstraint:0x7b05c6c0 H:|-(0)-[UIToolbar:0x7b069f10]   (Names: '|':UIView:0x7b064990 )>,
<NSLayoutConstraint:0x7b05c670 H:[UIToolbar:0x7b069f10]-(0)-|   (Names: '|':UIView:0x7b064990 )>

景观限制:

<NSLayoutConstraint:0x7b05c530 V:|-(0)-[_UILayoutGuide:0x7b0648a0]   (Names: '|':UIView:0x7b064990 )>,
<NSLayoutConstraint:0x7b05c4e0 V:[_UILayoutGuide:0x7b0648a0]-(0)-[UISearchBar:0x7b0e9590]>,
<NSLayoutConstraint:0x7b05c4b0 V:[UISearchBar:0x7b0e9590]-(0)-[UIView:0x7b0e9210]>,
<NSLayoutConstraint:0x7b05c480 V:[UIView:0x7b0e9210]-(0)-[UIToolbar:0x7b069f10]>,
<NSLayoutConstraint:0x7b05c450 V:[UIToolbar:0x7b069f10]-(0)-|   (Names: '|':UIView:0x7b064990 )>,
<NSLayoutConstraint:0x7b05c290 V:|-(0)-[_UILayoutGuide:0x7b0648a0]   (Names: '|':UIView:0x7b064990 )>,
<NSLayoutConstraint:0x7b05c240 V:[_UILayoutGuide:0x7b0648a0]-(0)-[UISearchBar:0x7b0e9590]>,
<NSLayoutConstraint:0x7b05c210 V:[UISearchBar:0x7b0e9590]-(0)-[UITableView:0x7cb4d600]>,
<NSLayoutConstraint:0x7b05c1e0 V:[UITableView:0x7cb4d600]-(0)-[UIToolbar:0x7b069f10]>,
<NSLayoutConstraint:0x7b05c1b0 V:[UIToolbar:0x7b069f10]-(0)-|   (Names: '|':UIView:0x7b064990 )>,
<NSLayoutConstraint:0x7b05bf70 H:|-(0)-[UITableView:0x7cb4d600]   (Names: '|':UIView:0x7b064990 )>,
<NSLayoutConstraint:0x7b05bf20 H:[UITableView:0x7cb4d600]-(0)-[UIView:0x7b0e9210]>,
<NSLayoutConstraint:0x7b05bef0 H:[UIView:0x7b0e9210]-(0)-|   (Names: '|':UIView:0x7b064990 )>,
<NSLayoutConstraint:0x7b05c2f0 UIView:0x7b0e9210.height == 0.75*UIView:0x7b0e9210.width>,
<NSLayoutConstraint:0x7b05be30 H:|-(0)-[UISearchBar:0x7b0e9590]   (Names: '|':UIView:0x7b064990 )>,
<NSLayoutConstraint:0x7b05bde0 H:[UISearchBar:0x7b0e9590]-(0)-|   (Names: '|':UIView:0x7b064990 )>,
<NSLayoutConstraint:0x7b05bd70 H:|-(0)-[UIToolbar:0x7b069f10]   (Names: '|':UIView:0x7b064990 )>,
<NSLayoutConstraint:0x7b05bd20 H:[UIToolbar:0x7b069f10]-(0)-|   (Names: '|':UIView:0x7b064990 )>

我还为此提交了一份 Apple 错误报告和 TSI,并得到了很好的答复。

在设备返回的方向改变之前调用方法的解决方案取决于您想要支持的iOS版本。

iOS < 8 willRotateToInterfaceOrientation:

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
    [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];

    [self.view setNeedsUpdateConstraints];
}

iOS 8+ viewWillTransitionToSize: 并进行一些检查以确定我们所处的方向。

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{
    if (size.width < size.height && self.view.bounds.size.width > self.view.bounds.size.height) {
        [NSLayoutConstraint deactivateConstraints:landscapeConstraints];
    } else if (size.width > size.height && self.view.bounds.size.width < self.view.bounds.size.height) {
        [NSLayoutConstraint deactivateConstraints:portraitConstraints];
    }
    [self.view setNeedsUpdateConstraints];
}