56

主に、編集可能なフィールド要素 (通常は 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:これらの制約を 1 つずつ削除して、特に問題を引き起こしている制約があるかどうかを確認しようとしましたが、それらはすべて、呼び出し時に、または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 ******/
4

13 に答える 13

3

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.

于 2015-03-31T03:04:01.270 に答える
2

@smileyborg の素晴らしい回答をより実用的なものにするには:

これは、浮動小数点の精度の問題が発生する可能性のある乗数の制約がある場合に発生する可能性があります。

解決するには:

  1. 乗数を持つすべての制約を確認します (レイアウト コードで、またはストーリーボード/ペン先を手動で編集して を検索しmultiplier=ます)。
  2. 乗数が 2 の「きれいな」累乗でない場合は、最も近いものに変えます (浮動小数点計算機を使用できます) 。

2 を行う簡単な方法は、必要な数値と計算機を入力し、その値が計算機の下部にある丸められた 10 進値と一致するまで、仮数部の精度の低いビットをオフにすることです。

于 2016-03-08T22:14:12.157 に答える
2

iOS バージョン > 8.0 でこの問題が発生した場合、Apple のドキュメントには、UIView の removeConstraint/addConstraint 関数ではなく、NSLayoutConstraint の「アクティブ」プロパティを使用するように記載されています。Apple Docs addConstraint リファレンス

于 2016-04-15T22:04:34.683 に答える
1

私にとっての問題は、UICollectionViewCell のプロパティを設定しているときに dequeueReusableCellWithReuseIdentifier を呼び出した後、自分に合ったタイミングで制約を削除していたことです。解決策は、代わりに次を呼び出すことでした。

    [_myUICollectionViewCell setNeedsUpdateConstraints];

そして上書きします:

    -(void)updateConstraints 

そこで私のいじりをします。好きなときに制約を削除することはできないようです。

于 2015-07-16T19:41:29.313 に答える
0

nil 引数を指定して removeConstraints: を呼び出すと、このクラッシュが発生します。

于 2014-12-02T15:09:44.600 に答える
0

このスレッドの他の回答は、これがどういうわけか無効な自動レイアウト/制約の問題であることを示していますが、「無効」と見なされるものについては非常に細かいようです。

幸いなことに、前回のコミット以降、多くの変更を行っておらず、問題のある変更を追跡することができました。UIImageView私にとっては、幅が同じで縦横比が 2:3 に固定された10 の水平ビューを持つことが問題でした。

クラッシュは、UIViewControllerこのイメージ行を含む を離れた後にのみ発生したようです。にそれぞれUIImageView設定しましたUIViewContentModeScaleAspectFill。このコンテンツ モードの変更 ( UIImages が設定される前に行われた) を削除すると、問題が解決したように見えましたが、受け入れられる解決策ではありませんでした。縦横比の制限を取り除き、各画像に固定の幅と高さを使用することになりました。

これが私のアプリケーションをクラッシュさせた理由はわかりません... クラッシュは、iOS 7.1.2 を実行している iPhone 4s でのみ再現することもできます。iOS 9.1 を実行している iPhone 4s シミュレーターで同じクラッシュを再現しようとしましたが、成功しませんでした。また、iOS 9.1 を実行している物理的な iPhone 5 で実行してもクラッシュしません。

それが誰かを助けることを願っています

于 2016-01-01T23:03:30.017 に答える
0

アップルのドキュメントによると:

iOS 8.0 以降向けに開発する場合は、addConstraint: メソッドを直接呼び出すのではなく、制約のアクティブプロパティをYESに設定します。アクティブなプロパティは、正しいビューから制約を自動的に追加および削除します。

私の場合、幅の制約を変更する必要がありました

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
            }
        }
于 2016-08-05T13:28:02.517 に答える
0

MZFormSheetControllerポッドでこの問題が発生しました: 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;
于 2014-04-02T16:07:58.740 に答える
0

wAnyhAny モードで制約が欠落しているときにこのクラッシュが発生しましたが、これを修正するとエラーが解消されました。

于 2015-08-27T12:02:35.753 に答える