【问题标题】:AutoLayout: removeFromSuperview / removeConstraints throws exception and crashes hardAutoLayout:removeFromSuperview / removeConstraints 抛出异常并严重崩溃
【发布时间】:2013-07-15 07:58:15
【问题描述】:

我们有选择地使用自动布局约束,主要用于定位与可编辑字段元素(通常是 UITextView、UITextField)相关的标签。然而,自从为这些字段实现自动布局以来,每当我们卸载视图、解除分配等时,我们都会看到一个令人讨厌的异常和崩溃。异常正在发生,因为它试图在卸载视图之前从视图中移除约束。

我们的视图/控制器层次结构如下:

UITableViewController (plain style, but with cell appearance to mimic grouped style)
--> UITableViewCell
----> UIViewController (container for editable form)
------> UICollectionViewController (editable form)
--------> UICollectionViewCell
-----------> UIViewController (editable field)
--------------> UILabel (field label)                   **HAS CONSTRAINTS**
--------------> UITextView / UITextField (field value)  **HAS CONSTRAINTS**

很多时候,当上层表格单元被释放/替换/重新加载时,我们会看到一个巨大的异常,然后在它试图释放/卸载其中的视图层次结构时崩溃。

我试图通过捕获异常(无帮助)以及在解除分配/卸载(在viewWillDisappear: 中)之前强制删除受影响视图和所有子视图的所有约束来缓解崩溃似乎没有帮助。我什至试图一一消除这些限制,看看是否有一个特别导致问题的因素,但是当我们在容器上调用 removeConstraint:removeConstraints: 以准备消失时,所有这些限制都会爆炸。

我很困惑!这是我们的异常的 sn-p —— 大约有 3000 行被删掉了,所以如果你需要更多,尽管问。

Exception while deallocating view: { Rows:
    0x18911270.posErrorMarker == 4 + 1*0x18911270.negError + 1*0x189112f0.marker + -1*0x189113f0.negError + 1*0x189113f0.posErrorMarker + 1*0x18911a60.marker + -0.5*0x1892dae0.negError + 0.5*0x1892dae0.posErrorMarker + 1*0x18951520.negError + -1*0x18951520.posErrorMarker + -0.5*0x18958090.negError + 0.5*0x18958090.posErrorMarker
    0x189112b0.negError == 12 + 1*0x189112b0.posErrorMarker + -1*0x189112f0.marker + 1*0x189113f0.negError + -1*0x189113f0.posErrorMarker + -1*0x18911a60.marker + 1*0x18925530.marker + 0.5*0x1892dae0.negError + -0.5*0x1892dae0.posErrorMarker + 1*0x1893e080.marker + 0.5*0x18958090.negError + -0.5*0x18958090.posErrorMarker + 1*0x18963640.marker
    0x18911370.negError == 9 + -1*0x189112f0.marker + 1*0x18911370.posErrorMarker + 1*0x18925530.marker + 1*0x1892dae0.negError + -1*0x1892dae0.posErrorMarker + 1*0x1893e080.marker + 1*0x18963640.marker
    0x189113b0.slackMarker == 2 + -1*0x189107d0.marker + 1*0x18910b90.negError + -1*0x18910b90.posErrorMarker + 

      ........ EXPLETIVES DELETED .........

   UITableView:0xca2b000.contentHeight == 36 + 1*0xc221c00.marker
   UITableView:0xca2b000.contentWidth == 704 + 1*0xc239470.marker
   UITableView:0xca2b000.minX == 0 + 1*0xc2a23f0.marker + -0.5*0xc2a2590.marker
   UITableView:0xca2b000.minY == 0 + 1*0xc2a25d0.marker + -0.5*0xc2a2630.marker
   UITableViewCellContentView:0x18ab13d0.Height == 174 + 1*0x18abd4f0.marker
   UITableViewCellContentView:0x18ab13d0.Width == 704 + 1*0x18abd470.marker

      ........ EXPLETIVES DELETED .........

    <NSAutoresizingMaskLayoutConstraint:0x18988bc0 h=-&- v=-&- UIView:0x18911e50.midY == UIView:0x1892d0c0.midY>        Marker:0x18988bc0.marker
    <NSAutoresizingMaskLayoutConstraint:0x18994b40 h=-&- v=-&- UIView:0xc4a6fb0.midX == UIView:0xc4b4990.midX>      Marker:0x18994b40.marker
    <NSAutoresizingMaskLayoutConstraint:0x18998480 h=-&- v=-&- UIView:0x18915180.width == UIView:0xc4c5970.width>       Marker:0x18998480.marker
    <NSAutoresizingMaskLayoutConstraint:0x18aae320 h=--& v=--& TapSectionalTableViewCell:0x18a3d270.midX == + 352>      Marker:0x18aae320.marker
    <NSAutoresizingMaskLayoutConstraint:0x18aae410 h=--& v=--& H:[TapSectionalTableViewCell:0x18a3d270(704)]>       Marker:0x18aae410.marker
    <NSAutoresizingMaskLayoutConstraint:0x18aae450 h=--& v=--& TapSectionalTableViewCell:0x18a3d270.midY == + 144>      Marker:0x18aae450.marker

      ........ EXPLETIVES DELETED .........

    <NSAutoresizingMaskLayoutConstraint:0xc2de2f0 h=--& v=--& TapGenericCollectionCell:0xc2ac500.midX == + 499>     Marker:0xc2de2f0.marker
    <NSAutoresizingMaskLayoutConstraint:0xc2de3b0 h=--& v=--& V:[TapGenericCollectionCell:0xc2ac500(34)]>       Marker:0xc2de3b0.marker
    <NSAutoresizingMaskLayoutConstraint:0xc2de430 h=-&- v=-&- UIView:0x18953f80.height == UIView:0xc2acb20.height>      Marker:0xc2de430.marker
    <NSAutoresizingMaskLayoutConstraint:0xc2de520 h=-&- v=-&- UIView:0x18923af0.height == UIView:0xc2ae570.height>      Marker:0xc2de520.marker
    <NSAutoresizingMaskLayoutConstraint:0xc2de560 h=--& v=--& H:[TapGenericCollectionCell:0xc2ac500(280)]>      Marker:0xc2de560.marker

      ........ EXPLETIVES DELETED .........

    <NSContentSizeLayoutConstraint:0xc2f5730 H:[_UIBaselineLayoutStrut:0x18994a30(0)] Hug:250 CompressionResistance:750>        Marker:0xc2f5730.posErrorMarker
    <NSContentSizeLayoutConstraint:0xc2f5730 H:[_UIBaselineLayoutStrut:0x18994a30(0)] Hug:250 CompressionResistance:750>        Marker:0xc2f5730.posErrorMarker
    <NSContentSizeLayoutConstraint:0xc2f5770 V:[_UIBaselineLayoutStrut:0x18994a30(18)] Hug:250 CompressionResistance:750>       Marker:0xc2f5770.posErrorMarker

internal error.  Cannot find an outgoing row head for incoming head UIView:0x189712b0.Width, which should never happen.'
/**** BEGIN Individual Field Controller - This code is from the base individual field controller used in our editable form collection *****/

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.clipsToBounds = YES;
    self.view.opaque = YES;

    CGRect viewFrame = self.view.frame;
    viewFrame.size = [self defaultFieldSize];
    self.view.frame = viewFrame;

    if (self.backgroundColor) {
        self.view.backgroundColor = self.backgroundColor;
    }
    else {
        self.view.backgroundColor = [UIColor whiteColor];
    }
    [self createLabelAndField];

    [self setLabelAndFieldContraints];

    [self.view addConstraints:self.labelValueConstraints];
    [self.view setNeedsUpdateConstraints];
}

- (void)createLabelAndField {
    [self removeLabelAndField];

    UILabel *label = [[UILabel alloc] init];
    label.font = self.labelFont;
    label.textColor = self.labelColor;
    label.lineBreakMode = NSLineBreakByWordWrapping;
    label.textAlignment = NSTextAlignmentLeft;
    label.adjustsFontSizeToFitWidth = NO;
    label.numberOfLines = 0;

    if (self.backgroundColor) {
        label.backgroundColor = self.backgroundColor;
    }
    else {
        label.backgroundColor = [UIColor whiteColor];
    }

    [self.view addSubview:label];

    self.label = label;


    /// EXAMPLE valueView initialization from a subclass that handles long text

    TapEditableTextView *textView = [[TapEditableTextView alloc] init];
    if (self.hasLabelOverValue) {
        textView.shouldMimicTextField = NO;
    }
    else {
        textView.shouldMimicTextField = YES;
    }
    textView.delegate = self;
    textView.keyboardType = UIKeyboardTypeDefault;
    textView.font = self.valueFont;
    textView.textColor = self.valueColor;
    textView.textAlignment = NSTextAlignmentLeft;
    textView.normalBackgroundColor = self.backgroundColor;
    textView.editable = NO;
    textView.textLines = self.textLines;

    self.valueTextView = textView;
    self.valueView = textView;
    [self.view addSubview:textView];
}

- (void)removeLabelAndField {
    [self clearConstraints];

    if (self.label) {
        [self.label removeFromSuperview];
        self.label = nil;
    }
    if (self.valueView) {
        [self.valueView removeFromSuperview];
        self.valueView = nil;
    }
}

- (void)clearConstraints {
    if (self.isViewLoaded && self.labelValueConstraints) {
        [self.view removeConstraints:self.labelValueConstraints];
    }
    self.labelValueConstraints = nil;
    self.labelToValueHorizConstraint = nil;
    self.valueWidthConstraint = nil;
}

// This is called in our field's viewDidLoad, after we've created our label and valueView (UITextField, UITextView, etc)
- (void)setLabelAndFieldContraints {
    [self clearConstraints];

    self.labelValueConstraints = [NSMutableArray array];

    self.label.translatesAutoresizingMaskIntoConstraints = NO;
    self.valueView.translatesAutoresizingMaskIntoConstraints = NO;

    NSLayoutConstraint *constraint = nil;

    constraint = [NSLayoutConstraint
                  constraintWithItem:self.label attribute:NSLayoutAttributeLeft
                  relatedBy:NSLayoutRelationEqual
                  toItem:self.view attribute:NSLayoutAttributeLeft
                  multiplier:1.0f constant:self.labelValueGap];
    constraint.priority = UILayoutPriorityRequired;
    [self.labelValueConstraints addObject:constraint];


    constraint = [NSLayoutConstraint
                  constraintWithItem:self.label attribute:NSLayoutAttributeTop
                  relatedBy:NSLayoutRelationEqual
                  toItem:self.view attribute:NSLayoutAttributeTop
                  multiplier:1.0f constant:0];
    constraint.priority = 550;
    [self.labelValueConstraints addObject:constraint];


    constraint = [NSLayoutConstraint
                  constraintWithItem:self.label attribute:NSLayoutAttributeBottom
                  relatedBy:NSLayoutRelationEqual
                  toItem:self.view attribute:NSLayoutAttributeBottom
                  multiplier:1.0f constant:0];
    constraint.priority = 400;
    [self.labelValueConstraints addObject:constraint];


    constraint = [NSLayoutConstraint
                  constraintWithItem:self.valueView attribute:NSLayoutAttributeTop
                  relatedBy:NSLayoutRelationEqual
                  toItem:self.view attribute:NSLayoutAttributeTop
                  multiplier:1.0f constant:0];
    constraint.priority = UILayoutPriorityRequired;
    [self.labelValueConstraints addObject:constraint];


    constraint = [NSLayoutConstraint
                  constraintWithItem:self.valueView attribute:NSLayoutAttributeBottom
                  relatedBy:NSLayoutRelationEqual
                  toItem:self.view attribute:NSLayoutAttributeBottom
                  multiplier:1.0f constant:0];
    constraint.priority = 499;
    [self.labelValueConstraints addObject:constraint];


     constraint = [NSLayoutConstraint
                  constraintWithItem:self.valueView attribute:NSLayoutAttributeRight
                  relatedBy:NSLayoutRelationEqual
                  toItem:self.view attribute:NSLayoutAttributeRight
                  multiplier:1.0f constant: -(kDisclosureWidth + self.labelValueGap) ];
     constraint.priority = 901;
     [self.labelValueConstraints addObject:constraint];


    constraint = [NSLayoutConstraint
                  constraintWithItem:self.valueView attribute:NSLayoutAttributeLeading
                  relatedBy:NSLayoutRelationGreaterThanOrEqual
                  toItem:self.label attribute:NSLayoutAttributeTrailing
                  multiplier:1.0f constant:self.labelValueGap];
    constraint.priority = UILayoutPriorityDefaultHigh + 1;
    [self.labelValueConstraints addObject:constraint];
    self.labelToValueHorizConstraint = constraint;


    constraint = [NSLayoutConstraint
                  constraintWithItem:self.label attribute:NSLayoutAttributeBaseline
                  relatedBy:NSLayoutRelationEqual
                  toItem:self.valueView attribute:NSLayoutAttributeBaseline
                  multiplier:1.0f constant:0.f];
    constraint.priority = 600;
    [self.labelValueConstraints addObject:constraint];


    constraint = [NSLayoutConstraint
                  constraintWithItem:self.valueView attribute:NSLayoutAttributeWidth
                  relatedBy:NSLayoutRelationEqual
                  toItem:self.view attribute:NSLayoutAttributeWidth
                  multiplier:(1.f - self.labelWidthPercentage) constant:0];
    constraint.priority = 305;
    [self.labelValueConstraints addObject:constraint];
    self.valueWidthConstraint = constraint;


    [self setCompressionAndHuggingForLabelView:self.label];
    [self setCompressionAndHuggingForValueView:self.valueView];
}

- (void)setCompressionAndHuggingForLabelView:(UILabel *)labelView {
    if (!labelView) {
        return;
    }
    [labelView setContentCompressionResistancePriority:510 forAxis:UILayoutConstraintAxisHorizontal];
    [labelView setContentCompressionResistancePriority:UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisVertical];
    [labelView setContentHuggingPriority:450 forAxis:UILayoutConstraintAxisHorizontal];
    [labelView setContentHuggingPriority:UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisVertical];
}

- (void)setCompressionAndHuggingForValueView:(UIView *)valueView {
    if (!valueView) {
        return;
    }
    [valueView setContentCompressionResistancePriority:509 forAxis:UILayoutConstraintAxisHorizontal];
    [valueView setContentCompressionResistancePriority:UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisVertical];
    [valueView setContentHuggingPriority:300 forAxis:UILayoutConstraintAxisHorizontal];
    [valueView setContentHuggingPriority:650 forAxis:UILayoutConstraintAxisVertical];
}

/****** END Individual Field Controller ******/

【问题讨论】:

  • 只是好奇,您是在后台线程上进行这些更改吗?其次,viewDidDisappear 而不是 viewWillDisappear 呢?
  • 另外,1) Cocoa Touch 框架中的异常被视为致命错误;不要试图抓住它们来解决它们,2)我们可以看到一些代码吗?
  • 请注意,我认为当您添加所有这些约束时,您不需要调用setNeedsUpdateConstraints,而是调用setNeedsLayout。根据updateConstraints 上的文档,“自己设置约束的自定义视图应该通过覆盖此方法来实现。”怀疑这是问题所在。代码看起来一般。一般需要有关您的应用程序的更多信息:您在使用 CoreData 吗?什么是“可编辑表单集合”?这里的结构是什么? :)
  • 我明白了。好吧,我的直觉说在后台线程上发生了某种调用,或者以某种方式违反了 UIKit 的程序。这就是你得到 NSInternalInconsistency 错误的原因;我过去也遇到过类似的事情。但是如果没有看到你的整个项目,我真的无法发现它。类似的建议在这里:twitter.com/radiantav/status/296588220626509824 ...如果您认为某人的推文是权威 XD
  • 脏话?给我看未经审查的例外!

标签: ios automatic-ref-counting autolayout


【解决方案1】:

我与一位 Apple 工程师就这次崩溃进行了(广泛的)交谈。

以下是两个最可能的原因:

  1. 您有一个无效的约束,例如view1.left = view2.left + 20,其中view2 意外为零,或者乘数为0。请务必双重(和三重)检查您的约束以确保它们是正确的。以下是 2 个有问题的约束示例:

    // The first constraint would be a problem if view2 were nil
    [NSLayoutConstraint constraintWithItem:view1 attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:view2 attribute:NSLayoutAttributeBottom multiplier:1 constant:20];
    // The second constraint is a problem because the 0 multiplier causes view2 to be "lost"
    [NSLayoutConstraint constraintWithItem:view1 attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:view2 attribute:NSLayoutAttributeBottom multiplier:0 constant:5];
    
  2. 您遇到了与浮点精度累积损失有关的内部 Foundation 自动布局引擎中的错误。当您崩溃时,您可以知道这种情况的方法是在控制台中的(大)异常日志中搜索一个非常小的(几乎为零)浮点数,例如:

    李>

&lt;505:-7.45058e-08&gt;*PWPlotLegendEntryView:0x600000582be0.Height{id: 34609} +

(在控制台输出中搜索e- 以找到像这样的小数字。)这个数字(在这种情况下为-7.45058e-08)表示在​​内部引擎解决约束时这个特定时间点的系数。在这种情况下,这个数字应该正好是 0,但是由于自动布局引擎使用浮点数进行计算的方式,它变成了一个非常小的负数,而不是把一切都搞砸了。如果你能在输出中找到这样的数字,你就知道你遇到了这个错误。

您如何解决这个问题?

更改添加(激活)约束的顺序最终可能会更改内部引擎中的计算顺序,结果可能会导致此问题消失,因为计算完成后不会出现任何问题的精度损失。

当您更改视图的内容压缩阻力或内容拥抱优先级时,此问题似乎更频繁地出现,因此请尝试注释掉任何执行此操作的代码以查看是否导致此错误发生,或重新排序在约束设置代码中早晚发生。

关于我的具体案例的更多详细信息:

我在 iOS 上遇到了这个崩溃。重现它的步骤非常有趣:

  1. 一个包含表格视图的视图控制器被推送到屏幕上(在导航控制器中)。
  2. 表格视图必须包含足够多的单元格,因此它们不能全部放入可见区域,然后它必须滚动到最后一个单元格,然后再向后退一点(推测这会导致单元格被重用,触发了这个问题)。
  3. 然后,当包含表格视图的视图控制器从导航堆栈中弹出时,在弹出动画完成后,应用程序将在视图控制器的视图从视图层次结构中删除的位置立即崩溃。

经过大量试验和错误后,我能够将问题隔离为一件特定的事情:在每个表格视图单元格中为 UIImageView 设置内容压缩阻力和拥抱优先级。在这种情况下,图像视图是使用单元格内的自动布局来定位的,为了实现正确的布局,图像视图需要与其固有的内容大小(图像的大小)完全一致。

这是有问题的代码:

// Inside of the UITableViewCell's updateConstraints method...

[self.imageView setContentCompressionResistancePriority:​UILayoutPriorityRequired forAxis:​UILayoutConstraintAxisHorizontal];        
[self.imageView setContentCompressionResistancePriority:​UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];       
[self.imageView setContentHuggingPriority:​UILayoutPriorityRequired forAxis:​UILayoutConstraintAxisHorizontal];      
[self.imageView setContentHuggingPriority:​UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];

删除上面的代码并将其替换为 2 个约束(在必需的优先级)以将图像视图的宽度和高度固定为图像的大小,实现了相同的结果,但避免了崩溃。这是替换代码(使用PureLayout):

[self.imageView autoSetDimensionsToSize:self.imageView.image.size];

我还发现,只需将有问题的 4 行移到我的约束设置代码中的不同位置即可解决问题,大概是因为这充分改变了计算顺序以防止有问题的精度损失。

【讨论】:

  • 这个答案救了我们的培根!由于浮点错误,我们的视图 only 在 iPad 2 上崩溃。将乘数设置为 1.6 到 1.59999 可以修复它。
  • @smileyborg -- 这是一些很棒的调查工作......很好的答案!
  • 我遇到了同样的问题,当我再次弹出它时,我使用 Autolayout 布局的子视图推送的模态视图崩溃了。我将约束添加到包含在将宽度设置为 0.8 作为视图控制器视图的乘数中的 UIView 中,其中添加了约束。这是在代码中完成的。将该值设置为 0.8 以外的任何值意味着应用程序不会崩溃。一个非常奇怪的错误。
  • 自从我提出原始问题以来,我已经多次遇到这个问题。对于我的情况,它似乎是以下几种情况的组合:(1)您上面提到的浮点精度下降(2)一次删除一个约束,而不是一次删除所有本地创建的约束(现在使用 deactivateConstraints)和(3)对非一元的约束具有不必要的“必需”优先级——我现在使用一个唯一分配优先级池来处理范围从 880-995 的那些约束——除非是一元,否则永远不会是 1000。
  • StackOv 的最佳答案之一!我将所有乘数更改为 1.999、0.333、1.449、0.799 等数字(感谢 cmets 的建议)。
【解决方案2】:

释放问题——一种可能性

您的使用自动布局的代码很可能在主线程上运行,但是在后台运行并使用您的视图(可能是间接地)的块之一可能持有对视图或其所有者的一个类似视图的强引用控制器(这是 Objective-C 块的默认行为)。当这样的块在后台队列上运行和释放时,它捕获的强引用会在同一个队列上释放,您可能会遇到众所周知的deallocation problem

  1. 在您的视图控制器中,确保在所有不需要需要强引用(并且可能在后台运行)的块中使用对self 的弱引用。您可以像这样声明它:__weak typeof(self) weakSelf = self; 在块之前 - 并在块内使用 weakSelf

  2. 任何持有对视图的引用的局部变量也是如此——确保它们的值被捕获为弱引用。

另一种可能性

在我的工作中,当隐藏视图参与布局时,我在 iOS 6 上遇到了类似的问题。从层次结构中删除视图 (-[UIView removeFromSuperview]) 而不是将 hidden 属性设置为 YES 为我解决了这个问题。

【讨论】:

  • 优秀的分数。我不知道这是否解决了我的问题(我已经重构了大部分相关代码),但这当然是合理的。我没有考虑到释放问题——这太棒了。
  • 谢谢@GregCombs!很高兴这对您将来有帮助。
【解决方案3】:

遇到了同样的问题,通过在 IB 中一次删除一个约束来解决它,直到崩溃解决。这将其缩小到有问题的约束。然后我恢复了上述约束,但颠倒了这些项目:

您可能很幸运,能够轻松解决您的 AL 问题。

【讨论】:

  • 当然,为什么对称算子(等于)是对称的?
  • @RhythmicFistman 由于约束被添加到自动布局引擎 (NSISEngine) 中的方式,看起来对称的约束可能实际上并不存在。至少,颠倒双方可能会改变执行计算的顺序,这可能会暴露(或避免)Apple 在 SDK 中的错误。
  • 意识到自动布局的约束求解器使用浮点数有助于解释它的一些奇怪行为!我从来没想过那个。谢谢,@smileyborg!
【解决方案4】:

对于在任何 iOS 版本 > 8.0 中遇到此问题的任何人,Apple 文档声明使用 NSLayoutConstraint 上的“活动”属性,而不是 UIView 上的 removeConstraint/addConstraint 函数。 Apple Docs addConstraint reference

【讨论】:

    【解决方案5】:

    为了让@smileyborg 的精彩回答更具可操作性:

    如果您对乘数有任何约束,可能会遇到浮点精度问题,就会发生这种情况。

    解决:

    1. 检查所有具有乘数的约束(在布局代码中或通过手动编辑情节提要/笔尖并搜索 multiplier=)。
    2. 如果乘数不是两个浮点数的“漂亮”幂,请将其转为最接近的一个(您可以使用floating point calculator

    做2的简单方法是输入你想要的数字和计算器,然后关闭尾数中的低精度位,直到该值与计算器底部的四舍五入的十进制值匹配。

    【讨论】:

      【解决方案6】:

      在我的例子中,它是一个比例宽度约束,乘数为 8:9。我把它改成了 7:9,它工作了。

      顺便说一句,找到约束的最简单方法是开始从视图控制器中删除视图。使用二进制算法:) 删除一半的视图,然后是导致应用崩溃的一半,等等。

      【讨论】:

      • 就你而言,这听起来像是@yonix 所指的浮点精度问题。
      • 正确,但是当我发布答案时,yonix的答案不存在。
      【解决方案7】:

      对我来说,问题是在设置 UICollectionViewCell 的属性时调用 dequeueReusableCellWithReuseIdentifier 之后,我正在删除一个适合我的约束。解决方案是改为调用:

          [_myUICollectionViewCell setNeedsUpdateConstraints];
      

      并覆盖:

          -(void)updateConstraints 
      

      然后在那里做我的事情。看来你不能随心所欲地删除约束。

      【讨论】:

        【解决方案8】:

        我刚刚在 OSX Mavericks 下偶然发现了与我正在开发的 OSX 应用程序相同的错误,但与给出的其他答案不同,我绝对没有任何其他线程与 UI 对象交互,并且有问题的视图层次结构也绝对可见。我也没有使用积木。奇怪的是,当我移除 NSTextField 上的垂直约束时,问题就消失了。

        FWIW 有问题的视图从其父视图中删除会导致“内部错误。找不到传入行头的传出行头”错误是许多侧面板控件之一,它们一起在主视图中呈现对象的属性,可以被剪切、复制、创建等。这意味着用户可以非常快速地将新对象粘贴到主视图中,这意味着侧面板的控件正在被破坏并且新的控件也被快速创建。当然,对于主线程中的所有内容,这应该没什么区别,但似乎有所不同。

        导致问题的确切约束是

        [自我添加约束: [NSLayoutConstraint 约束与项目:控制 属性:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual 到项目:其他 属性:NSLayoutAttributeHeight 乘数:1.4 常数:0.0]];

        其中 control 是导致问题的(可编辑的)NSTextField,而“other”是另一个(不可编辑的)NSTextField 标签。

        【讨论】:

        • 这个答案为我解决了这个问题。我在解雇之前删除了所有约束和视图,它可以工作。看起来有一些带有约束的浮点数学出了问题。
        【解决方案9】:

        MZFormSheetController pod: https://github.com/m1entus/MZFormSheetController/issues/78 遇到了这个问题

        此代码崩溃:

        [formSheetController.view addSubview:self.sharePanel];
        // ...
        [self.sharePanel removeFromSuperview]; // <-- CRASHES HERE
        

        我的解决方案很奇怪,但它有效:

        [self.sharePanel removeFromSuperview]; // <-- This line helps to avoid crash
        [formSheetController.view addSubview:self.sharePanel];
        // ...
        [self.sharePanel removeFromSuperview];
        

        这里是sharePanel 属性声明:

        @property (weak, nonatomic) IBOutlet UIView *sharePanel;
        

        【讨论】:

          【解决方案10】:

          当我使用 nil 参数调用 removeConstraints: 时,我遇到了这个崩溃。

          【讨论】:

            【解决方案11】:

            当我在 wAnyhAny 模式下仍然缺少约束时,我遇到了这个崩溃,修复这个问题消除了错误。

            【讨论】:

              【解决方案12】:

              正如该线程中的其他答案所表明的那样,这在某种程度上是一个无效的自动布局/约束问题,尽管它似乎对什么是“无效”非常挑剔。

              幸运的是,自上次提交以来,我没有进行太多更改,并且能够追踪到有问题的更改。对我来说,有 10 个水平的 UIImageView 具有相同的宽度和固定的 2:3 纵横比是问题所在。

              崩溃似乎只发生在离开包含此图像行的UIViewController 之后。每个UIImageView 都设置为UIViewContentModeScaleAspectFill。删除此内容模式更改(在设置 UIImages 之前完成)似乎解决了我的问题,但不是一个可接受的解决方案。我最终取消了纵横比限制,只为每张图片使用了固定的宽度和高度。

              我不知道为什么这会导致我的应用程序崩溃...崩溃也可能在运行 iOS 7.1.2 的 iPhone 4s 上重现。我试图在运行 iOS 9.1 的 iPhone 4s 模拟器上重现同样的崩溃,但没有成功。在运行 iOS 9.1 的物理 iPhone 5 上运行时,它也不会崩溃。

              希望能帮助到那里的人

              【讨论】:

                【解决方案13】:

                根据 Apple 文档:

                为 iOS 8.0 或更高版本开发时,将约束的 active 属性设置为 YES,而不是直接调用 addConstraint: 方法。 active 属性会自动在正确的视图中添加和删除约束。

                就我而言,我必须修改宽度限制

                for var constraint in self.navigationBar.constraints {
                            if constraint.identifier == "theProgressWidth" {
                                let sizeWidth = self.navigationBar.frame.size.width
                                constraint = NSLayoutConstraint(item: progress!, attribute: .Width, relatedBy: .Equal, toItem: self.navigationBar, attribute: .Width, multiplier: ((sizeWidth * (level / 100)) / sizeWidth), constant: 0)
                                constraint.active = true
                            }
                        }
                

                【讨论】:

                  猜你喜欢
                  • 2013-04-08
                  • 1970-01-01
                  • 1970-01-01
                  • 2022-09-30
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多