Ошибка при использовании activateConstraints для набора ограничений представления контейнера

В моем приложении для iOS 8, использующем классы размеров, чтобы iPad имел другой макет в портретной и альбомной ориентации, у меня есть IBOutletCollection для каждой ориентации, которую я активирую и деактивирую. Это отлично работало до появления Container View.

Я добавляю новый VC, который является отдельным элементом вкладки в версии для iPhone, но я встраиваю его в макет iPad с помощью представления контейнера. Я сосредоточусь только на классе одного размера, RegularRegular. Представление контейнера имеет 4 ограничения: конечное, ведущее, верхнее и нижнее. Когда я запускаю приложение, оно выглядит нормально (в этой единственной ориентации).

Теперь, когда я добавляю эти 4 ограничения в свой IBOutletCollection, сообщение activateConstraints завершается ошибкой со следующим сообщением об ошибке:

*** Завершение работы приложения из-за неперехваченного исключения «NSGenericException», причина: «Невозможно активировать ограничение с элементами; слой =; contentOffset: {0, 0}; contentSize: {460, 78}> и>, потому что у них нет общего предка. Указывает ли ограничение на элементы в разных иерархиях представлений? Это незаконно.

Ограничения не ссылаются на элементы в разных иерархиях представлений. Top, Bottom и Leading связаны с другим представлением, которое также находится в представлении VC. Трейлинг связан с шаговым двигателем, который также находится в поле зрения ВК. Так что, насколько мне известно, все они находятся на одном иерархическом уровне.

Во время отладки я вижу, что ограничение начинается с его свойства active как nil. Это кажется нормальным (неконтейнерные ограничения начинались так же, прежде чем они были установлены на YES). Я проверил это с помощью цикла for, установив свойство active.

Что-то я делаю не так с ограничениями в представлении контейнера? Являются ли ограничения в представлении контейнера чем-то особенным, потому что они находятся в представлении контейнера? Я сам пытался найти ответ, но не могу найти ничего в отношении этой проблемы.

Любая помощь будет принята с благодарностью.

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

На изображении ниже ограничения Leading, Top и Bottom контейнера связаны с видом справа от контейнера. Ограничение "Трейлинг" относится к шагающему над ним. Макет VC

Связанный код:

@property (strong, nonatomic) IBOutletCollection(NSLayoutConstraint) NSArray *regularAnyConstraints;
@property (strong, nonatomic) IBOutletCollection(NSLayoutConstraint) NSArray *regularAnyContainerConstraints;

@property (strong, nonatomic) IBOutletCollection(NSLayoutConstraint) NSArray *anyRegularConstraints;
@property (strong, nonatomic) IBOutletCollection(NSLayoutConstraint) NSArray *anyRegularContainerConstraints;

Это ограничения в массиве _anyRegularContainerConstraints: _ anyRegularContainerConstraints

[NSLayoutConstraint deactivateConstraints:_regularAnyConstraints];
[NSLayoutConstraint activateConstraints:_anyRegularConstraints];

[NSLayoutConstraint deactivateConstraints:_anyRegularContainerConstraints];
[NSLayoutConstraint activateConstraints:_anyRegularContainerConstraints];

person Kurt Anderson    schedule 10.04.2015    source источник


Ответы (2)


Во время отладки я вижу, что ограничение начинается с его активного свойства как nil

Это замечание заставляет меня задуматься, возможно, вы неправильно истолковываете то, что делают activateConstraints и deactivateConstraints. Несмотря на их названия и вводящую в заблуждение запись в документации, они фактически добавляют и удаляют ограничения. Таким образом, вместо того, чтобы запутывать себя этими командами, я бы посоветовал вам лучше вызвать addConstraints и removeConstraints напрямую. Преимущество этого:

  • Последние являются методами UIView, поэтому вы будете сознательно контролировать, к какому виду добавляются ограничения.

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

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

person matt    schedule 10.04.2015
comment
Я пробовал это, но, похоже, все еще получаю ошибку иерархии, что заставляет меня думать, что с моей иерархией определенно что-то не так, но я не знаю что. [self.containerView removeConstraints:_regularAnyContainerConstraints]; [self.containerView addConstraints:_anyRegularContainerConstraints]; Сообщение об ошибке: Иерархия представлений не подготовлена ​​для ограничения: ‹NSLayoutConstraint: 0x7a1ae970 UIView: 0x7a1ae9a0.bottom == UIView: 0x7a0546a0.bottom› При добавлении в представление элементы ограничения должны быть потомками этого представления (или представления сам). - person Kurt Anderson; 10.04.2015
comment
Что ж, представления контейнера довольно очевидны особенными. Я предполагаю, что моим следующим предложением будет: можете ли вы свести эту проблему к очень простому проекту? Затем вы можете опубликовать его на github, а затем я скачаю его и изучу подробности. - person matt; 10.04.2015
comment
Я должен был попытаться упростить его с самого начала. У меня нет проблем с активацией и деактивацией ограничений для представления контейнера из моего тестового проекта. Мне нужно дальше исследовать различия между ним и моим проектом приложения. Спасибо. - person Kurt Anderson; 11.04.2015
comment
Я не так уж удивлен. :) Я считаю, что создание упрощенной версии проблемы часто является лучшим способом начать ее отладку. Если ошибка все еще существует, это проще, а если ошибки нет, вы знаете, что проблема в другом. - person matt; 11.04.2015

Проблема заключалась в том, что представление контейнера не было «установлено» во время применения ограничений. Я деактивирую / выключаюсь из viewWillLayoutSubviews, поэтому в то время класс размера еще не должен быть определен.

Чтобы решить эту проблему, у меня теперь установлен Container View для AnyAny. Затем я снял выделение со всех классов размеров, для которых он не нужен.

В конце концов я обнаружил, что это проблема, потому что UIView моего представления контейнера не находился в self.view.subviews.

person Kurt Anderson    schedule 11.04.2015