programing

AutoLayout : removeFromSuperview / removeConstraints에서 예외가 발생하고 충돌이 심합니다.

goodcopy 2021. 1. 18. 22:07
반응형

AutoLayout : removeFromSuperview / removeConstraints에서 예외가 발생하고 충돌이 심합니다.


우리는 주로 편집 가능한 필드 요소 (일반적으로 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**

상위 레벨 테이블 셀이 할당 해제 / 교체 / 다시로드 될 때 여러 번 큰 예외가 발생하고 내부에서 뷰 계층을 할당 해제 / 언로드하려고 할 때 충돌이 발생합니다.

예외를 포착하고 (도움 없음), 할당 해제 / 언로드 전에 영향을받는 뷰와 모든 하위 뷰에 대한 모든 제약 조건을 강제로 제거하여 (in viewWillDisappear:) 충돌을 완화하려고 시도했지만 도움 이되지 않는 것 같습니다. . 특히 문제를 일으키는 것이 있는지 확인하기 위해 이러한 제약을 하나씩 제거하려고 시도했지만 사라질 준비를 위해 전화를 걸 removeConstraint:거나 removeConstraints:컨테이너에서 모두 폭발하고 있습니다.

당황 해요! 다음은 예외의 일부입니다. 약 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 ******/

이 충돌에 대해 Apple 엔지니어와 (광범위한) 대화를 나눴습니다.

가장 가능한 두 가지 원인은 다음과 같습니다.

  1. 당신은 같은 잘못된 제약,이 view1.left = view2.left + 20경우 view2예기치 않게 전무, 또는 0의 승수가 올바른지 있는지 확인하기 위해 점검 제한 조건 더블 (트리플)으로 확인이 있습니다. 다음은 문제가있는 제약 조건의 두 가지 예입니다.

    // 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 자동 레이아웃 엔진의 버그가 발생했습니다. 충돌이 발생했을 때 이것이 사실임을 알 수있는 방법은 다음과 같이 매우 작은 (거의 0) 부동 소수점 숫자에 대해 콘솔의 (대형) 예외 로그를 ​​검색하는 것입니다.

<505:-7.45058e-08>*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 줄을 다른 위치로 이동하는 것만으로도 문제가 해결된다는 사실을 발견했습니다. 아마도 이것이 문제가되는 정밀도 손실을 방지 할 수 있도록 계산 순서를 충분히 변경했기 때문일 것입니다.


할당 해제 문제-한 가지 가능성

자동 레이아웃과 함께 작동하는 코드는 메인 스레드에서 잘 실행될 수 있지만 백그라운드에서 실행되고 뷰를 사용하는 블록 중 하나 (아마도 간접적으로)는 뷰 또는 뷰 컨트롤러와 같은 소유자 중 하나에 대한 강력한 참조를 보유 할 수 있습니다 (즉, Objective-C 블록의 기본 동작). 이러한 블록이 실행되고 백그라운드 큐에서 할당 해제되면 캡처 한 강력한 참조가 동일한 큐에서 해제 되고 잘 알려진 할당 해제 문제에 직면 할 수 있습니다 .

  1. 뷰 컨트롤러에서 강력한 참조 가 필요self 하지 않은 모든 블록에서 약한 참조를 사용하고 있는지 확인하십시오 (백그라운드에서 실행될 수 있음). 다음과 같이 선언 할 수 있습니다 : before the block — and use inside the block.__weak typeof(self) weakSelf = self;weakSelf

  2. Same goes for any local variables that hold references to your views — make sure their values are captured as weak refs.

Another possibility

In my work, I've encountered a similar issue on iOS 6 when hidden view participated in layout. Removing the view from hierarchy (-[UIView removeFromSuperview]) instead of setting hidden property to YES fixed the issue for me.


Had the same issue, solved it by deleting constraints one at a time in IB until the crash was solved. This narrowed it down to the offending constraint. I then reinstated said constraint, but reversed the items:

enter image description here

You may be as lucky and be able to solve your AL problems as easily.


For anyone encountering this issue in any iOS version > 8.0, the Apple docs state to use the "active" property on the NSLayoutConstraint rather than the removeConstraint/addConstraint functions on UIView. Apple Docs addConstraint reference


To make @smileyborg's awesome answer more actionable:

This can happen if you have any constraints with multipliers that might suffer from floating point precision issues.

To solve:

  1. Go over all your constraints that have multipliers (in layout code or by manually editing a storyboard/nib and searching for multiplier=).
  2. If multiplier isn't a "pretty" power of two float, turn it to the nearest one (you can use a floating point calculator)

To easy way to do 2 is to enter the number you value you want and the calculator and then switch off lower precision bits in the mantissa until the value matches the rounded decimal value at bottom of the calculator.


In my case it was a proportional width constraint with 8:9 multiplier. I changed it to 7:9 and it worked.

BTW the easiest way to find a constraint is to start removing views from view controller. Do it using binary algorithm :) removing half views, then half of the half that makes app crash, etc.


For me the problem was that I was removing a constraint at a time that suited me, after calling dequeueReusableCellWithReuseIdentifier while setting properties of my UICollectionViewCell. The solution was to instead call:

    [_myUICollectionViewCell setNeedsUpdateConstraints];

and override:

    -(void)updateConstraints 

and do my messing there. Seems that you can't just remove constraints when you like.


I just stumbled across the same error under OSX Mavericks with an OSX app I'm developing, but unlike the other answers given, I definitely don't have any other threads interacting with the UI objects, and the view hierarchy in question is definitely visible too. I'm not using blocks either. Bizarrely the problem went away when I removed a vertical constraint on an NSTextField.

FWIW the problematic view whose removal from its superview causes the "internal error. Cannot find an outgoing row head for incoming head" error is one of many side-panel controls which together present the properties of objects in the main view which can be cut, copied, created etc. This means that the user can be pasting new objects into the main view quite rapidly, meaning the side-panel's controls are being destroyed and new ones created very rapidly, too. Of course, with everything in the main thread, this should not make a difference, but it seems to.

The exact constraint causing problems was

[self addConstraint: [NSLayoutConstraint constraintWithItem:control attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:other attribute:NSLayoutAttributeHeight multiplier:1.4 constant:0.0]];

where control is the (editable) NSTextField causing problems, and 'other' is another (non-editable) NSTextField label.


I got this problem with MZFormSheetController pod: https://github.com/m1entus/MZFormSheetController/issues/78

This code crashes:

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

My solution is very strange but it works:

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

And here is sharePanel property declaration:

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

I am getting this crash when I call removeConstraints: with a nil argument.


I got this crash when I still have a missing constraint in wAnyhAny mode, fixing this removed the error.


As the other answers in this thread indicate this is somehow an invalid autolayout/contraint problem, though it appears to be very finicky about what qualifies as "invalid".

Luckily I hadn't made many changes since my last commit and was able to track down the offending changes. For me having a view of 10 horizontal UIImageView with equal width and fixed 2:3 aspect ratio was the issue.

The crash only seemed to occur after leaving the UIViewController that contained this image row. Each UIImageView was set to UIViewContentModeScaleAspectFill. Removing this content mode change (which was done before the UIImages were set) seemed to fix my problem but wasn't an acceptable solution. I ended up removing the aspect ratio restriction and just using a fixed width and height for each image.

Why this was crashing my application I don't know... The crash could also ONLY be reproduce on an iPhone 4s running iOS 7.1.2. I tried to reproduce the same crash on an iPhone 4s simulator running iOS 9.1 without success. It also wouldn't crash when running on a phsyical iPhone 5 running iOS 9.1.

Hope that helps someone out there


According to Apple Documentation:

When developing for iOS 8.0 or later, set the constraint’s active property to YES instead of calling the addConstraint: method directly. The active property automatically adds and removes the constraint from the correct view.

In my case I had to modify the width constraint

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
            }
        }

ReferenceURL : https://stackoverflow.com/questions/17688370/autolayout-removefromsuperview-removeconstraints-throws-exception-and-crashes

반응형