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

Много раз, когда ячейки таблицы верхнего уровня освобождаются/заменяются/перезагружаются, мы видим огромное исключение, а затем сбой при попытке освободить/выгрузить иерархию представления внутри.

Я попытался смягчить крах, поймав исключение (без помощи), а также решительно удалив все ограничения на затронутое представление и все подпункты до освобождения/выгрузки (в 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 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 ******/

Ответ 1

У меня был обширный разговор с инженером Apple об этом сбое.

Вот две наиболее вероятные причины:

  • У вас есть недопустимое ограничение, например 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];
    
  • Вы попадаете в ошибку во внутреннем механизме компоновки основного флага, связанном с накопленной потерей точности с плавающей запятой. Когда вы разбились, то, как вы можете знать, что это так, - это поиск в журнале больших (больших) исключений в консоли для очень маленького (почти нулевого) числа с плавающей запятой, например:

<505:-7.45058e-08>*PWPlotLegendEntryView:0x600000582be0.Height{id: 34609} +

(Найдите e- в выводе консоли, чтобы найти такие маленькие числа.) Этот номер (-7.45058e-08 в этом случае) представляет коэффициент в этот конкретный момент времени, в то время как внутренний движок разрешает ограничения. В этом случае число должно быть ровно 0, но из-за того, как механизм автоматического компоновки выполняет вычисления с номерами с плавающей запятой, он стал чрезвычайно крошечным отрицательным числом, а это взрывает все. Если вы можете найти такое количество в выводе, вы знаете, что попали в эту ошибку.

Как вы можете обойти эту проблему?

Изменение порядка добавления (активации) ограничений может привести к изменению порядка вычислений во внутреннем движке, что в результате может привести к исчезновению этой проблемы, поскольку математика выполняется без какой-либо проблемной потери точности.

Эта проблема возникает чаще, когда вы изменили сопротивление сжатия содержимого или приоритизацию содержимого для просмотров, поэтому попробуйте прокомментировать любой код, который делает это, чтобы увидеть, вызвало ли это ошибку или переупорядочило ее произойдет раньше или позже в вашем установочном коде ограничения.

Подробнее о моем конкретном случае:

Я столкнулся с этим сбоем на iOS. Шаги по его воспроизведению были весьма интересными:

  • Контроллер представления, содержащий представление таблицы, был нажат на экран (в навигационном контроллере).
  • В представлении таблицы должно было быть достаточно ячеек, чтобы они не все соответствовали видимой области, затем ее нужно было прокрутить до последней ячейки, а затем немного скорректировать (предположительно, это вызывало повторное использование ячеек, который вызывал эту проблему).
  • Затем, когда контроллер представления, содержащий представление таблицы, был удален из стека навигации сразу после того, как поп-анимация завершилась, приложение потерпит крах в точке, где вид контроллера представления был удален из иерархии представлений.

После большого количества проб и ошибок я смог выделить проблему одной конкретной вещи: установить сопротивление сжатию содержимого и обнимать приоритеты для UIImageView в каждой из ячеек таблицы. В этом случае представление изображения позиционируется с использованием автоматического макета внутри ячейки, и для достижения правильной компоновки представление изображения должно быть именно его внутренним размером содержимого (размером его изображения).

Это был проблематичный код:

// Inside of the UITableViewCell 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 строк в другое место в моем установочном коде ограничения разрешило проблему, по-видимому, потому, что это значительно изменило порядок вычислений, чтобы предотвратить проблемную потерю точности.

Ответ 2

Проблема удаления - одна возможность

Ваш код, который работает с автоматической компоновкой, вполне может работать в основном потоке, но один из блоков, которые работают в фоновом режиме и использует ваше представление (возможно, косвенно), может содержать сильную ссылку на представление или на одного из его владельцев, например, на вид контроллер (это поведение по умолчанию блоков Objective-C). Когда такой блок запускается и освобождается в фоновом режиме, сильные ссылки, которые он фиксирует, освобождаются в этой же очереди, и вы можете столкнуться с хорошо известной проблемой удаления .

  • В вашем контроллере просмотра убедитесь, что вы используете слабую ссылку на self во всех блоках, которым не нужна сильная ссылка (и может выполняться в фоновом режиме). Вы можете объявить это следующим образом: __weak typeof(self) weakSelf = self; перед блоком - и использовать weakSelf внутри блока.

  • То же самое касается любых локальных переменных, которые содержат ссылки на ваши представления - убедитесь, что их значения зафиксированы как слабые ссылки.

Другая возможность

В моей работе я столкнулся с аналогичной проблемой в iOS 6, когда скрытый просмотр участвовал в макете. Удаление представления из иерархии (-[UIView removeFromSuperview]) вместо установки свойства hidden в YES устраняет проблему для меня.

Ответ 3

Имел ту же проблему, решил ее, удалив ограничения по одному в IB до тех пор, пока не была решена авария. Это сузило его до оскорбительного ограничения. Затем я восстановил указанное ограничение, но изменил позиции:

enter image description here

Вы можете быть счастливы и быть в состоянии решить ваши проблемы AL как легко.

Ответ 4

Чтобы сделать замечательный ответ @smileyborg более действенным:

Это может произойти, если у вас есть какие-либо ограничения с мультипликаторами, которые могут пострадать от проблем с плавающей запятой.

Чтобы решить:

  • Переходите ко всем вашим ограничениям, которые имеют множители (в коде макета или вручную редактируют раскадровку /nib и поиск multiplier=).
  • Если множитель не является "красивой" мощностью двух поплавков, переведите его к ближайшему (вы можете использовать калькулятор с плавающей запятой)

В простой способ сделать 2 нужно ввести нужный вам номер и калькулятор, а затем отключить биты более низкой точности в мантиссе, пока значение не будет соответствовать округленному десятичному значению внизу калькулятора.

Ответ 5

Для тех, кто сталкивается с этой проблемой в любой версии iOS > 8.0, Apple docs заявляют, что используют свойство "active" в NSLayoutConstraint, а не функции removeConstraint/addConstraint в UIView. Ссылка на документацию Apple Docs

Ответ 6

В моем случае это было пропорциональное ограничение ширины с множителем 8: 9. Я изменил его на 7: 9, и он сработал.

Кстати, самый простой способ найти ограничение - начать удаление просмотров из контроллера представления. Сделайте это с помощью двоичного алгоритма:) удалите половинные просмотры, затем половину половины, из-за которой произойдет сбой приложения и т.д.

Ответ 7

Для меня проблема заключалась в том, что я удалял ограничение в то время, которое мне подходит, после вызова dequeueReusableCellWithReuseIdentifier при настройке свойств моего UICollectionViewCell. Решением было вместо этого позвонить:

    [_myUICollectionViewCell setNeedsUpdateConstraints];

и переопределить:

    -(void)updateConstraints 

и сделай мой беспорядок там. Кажется, вы не можете просто удалить ограничения, когда захотите.

Ответ 8

Я просто наткнулся на ту же ошибку в OSX Mavericks с OSX-приложением, которое я разрабатываю, но, в отличие от других ответов, я определенно не имею никаких других потоков, взаимодействующих с объектами пользовательского интерфейса, и рассматриваемой иерархии представлений также определенно видно. Я тоже не использую блоки. Необычно проблема исчезла, когда я удалил вертикальное ограничение на NSTextField.

FWIW проблематичный вид, удаление которого из его супервизора вызывает "внутреннюю ошибку. Не удается найти исходящую строку заголовка для входящей головы". Ошибка - это один из многих элементов управления боковой панели, которые вместе представляют свойства объектов в главном представлении, которые могут быть отрезанным, скопированным, созданным и т.д. Это означает, что пользователь может быстро вставлять новые объекты в основной вид, то есть элементы управления боковой панели уничтожаются, а новые тоже создаются очень быстро. Конечно, со всем в основном потоке это не должно меняться, но кажется.

Точное ограничение, вызывающее проблемы, было

[self addConstraint:   [NSLayoutConstraint     constraintWithItem: контроль     Атрибут: NSLayoutAttributeHeight     relatedBy: NSLayoutRelationEqual     toItem: другие     Атрибут: NSLayoutAttributeHeight     Умножитель: 1.4     константа: 0.0]];

где управление является (редактируемым) NSTextField, вызывающим проблемы, а "другое" - это другая (не редактируемая) метка 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

Я получаю этот сбой, когда вызываю removeConstraints: с аргументом nil.

Ответ 11

Я получил этот сбой, когда у меня все еще есть недостающее ограничение в режиме wAnyhAny, исправление которого устранило ошибку.

Ответ 12

Как другие ответы в этом потоке указывают, что это как-то неверная проблема с автозапуском/противопоказанием, хотя, похоже, она очень тонкая в отношении того, что квалифицируется как "недействительный".

К счастью, я не внес много изменений с момента моего последнего коммита и смог отслеживать нарушающие изменения. Для меня было проблемой 10 горизонтальных UIImageView с равной шириной и фиксированным соотношением сторон 2: 3.

Казалось, что авария произошла после выхода из UIViewController, содержащего эту строку изображения. Для каждого параметра UIImageView установлено значение UIViewContentModeScaleAspectFill. Удаление этого изменения режима содержимого (которое было сделано до установки UIImage), казалось, устранило мою проблему, но не было приемлемым решением. Я закончил удаление ограничения формата и просто использовал фиксированную ширину и высоту для каждого изображения.

Почему это было сбой моего приложения, которого я не знаю... Возможно, авария с ТОЛЬКО будет воспроизводиться на iPhone 4 с iOS 7.1.2. Я попытался воспроизвести ту же ошибку на симуляторе iPhone 4s с iOS 9.1 без успеха. Это также не сработает при работе на phsyical iPhone 5 с iOS 9.1.

Надеюсь, что кто-то поможет там

Ответ 13

Согласно документации Apple:

При разработке для iOS 8.0 или более поздней версии установите для параметра активное свойство YES вместо прямого вызова метода addConstraint:. Активное свойство автоматически добавляет и удаляет ограничение из правильного представления.

В моем случае мне пришлось изменить ограничение ширины

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