Включить + Отключить ограничения автоматической компоновки
У меня есть простая (я думаю) проблема: у меня есть UIImageView
, на который я установил несколько ограничений для раскадровки.
Иногда мне нужно отключить ограничения и установить его frame
вручную, но позже я хочу снова включить эти ограничения и вернуть представление туда, где это было определено ограничениями,
Я думал, что смогу сделать это с чем-то вроде:
@IBOutlet weak var imageView: UIImageView!
@IBOutlet weak var constraint: NSLayoutConstraint!
func example() {
//to set its location and size manually
imageView.removeConstraint(constraint)
imageView.frame = CGRectMake(...)
//to cause it to return to its original position
imageView.addConstraint(constraint)
}
При этом, однако, я получаю ошибку 2015-08-26 01:14:55.417 Constraints[18472:923024] The view hierarchy is not prepared for the constraint: <NSLayoutConstraint:0x7fbb72815f90 V:[_UILayoutGuide:0x7fbb72814c20]-(100)-[UIImageView:0x7fbb72814540]>
. Кто-нибудь знает, почему возникает эта ошибка?
Добавление ограничений вместо view
путем вызова self.view.addConstraint(...)
устраняет ошибку, но не возвращает изображение обратно туда, где оно должно быть.
Я замечаю, что мне даже не нужно удалять и деактивировать ограничения, чтобы иметь возможность установить кадр imageView
без проблем, если я не вызываю setTranslatesAutoresizingMaskIntoConstraints(true)
.
Я уже видел этот вопрос, но ответ кажется излишне сложным, возможно устаревшим и даже неприменимым.
Я также видел этот вопрос, но это не охватывает ограничения, которые могут быть повторно активированы, - только то, как они могут быть отключены.
Попытка установить свойство active
:
self.top.active = false
self.right.active = false
self.bottom.active = false
self.left.active = false
imageView.frame = CGRectMake(100, 100, 100, 100)
Это фактически приводит к тому, что imageView
больше не отображается. (Если я не установил для всех свойств ограничений active
значение false, однако imageView
переместится в нужную позицию.
Реальная проблема заключается в том, что когда я пытаюсь вернуть представление изображения туда, где оно было, установив для всех свойств ограничений < active
значение true, ничего не происходит - изображениеView остается там, где оно было (в этом case, как указано в imageView.frame = CGRectMake(100, 100, 100, 100)
.
Кроме того, согласно моему тестированию и Joachim Bøggild ответьте здесь, что если для свойства ограничения active
установлено значение false, это ограничение становится равным нулю, и, следовательно, не может быть повторно активирована.
Добавление ограничений в массив и активация/деактивация их:
Интересно, что это вызывает почти те же проблемы, что и установка свойства active
. Размещение всех ограничений в массиве array
, а вызов NSLayoutConstraint.deactivateConstraints(array)
приводит к исчезновению изображения. Кроме того, повторная активация ограничений позже с помощью NSLayoutConstraint.activateConstraints(array)
не возвращает изображение в том месте, где оно должно - оно остается там, где оно было.
Ответы
Ответ 1
Ага!
Ограничения становятся nil (и, следовательно, не могут быть повторно активированы), как только их свойство active
установлено в false. Создание сильных ссылок (спасибо, Caleb, для очистки номенклатуры) сохраняет их, чтобы они могли быть активированы и деактивированы по желанию.
Ответ 2
Если вы посмотрите на документы для NSLayoutConstraint
, вы найдете раздел под названием Активация и деактивация ограничений, который описывает active
, которое, в свою очередь, сообщает вам:
Вы можете активировать или деактивировать ограничение, изменив это свойство... Активация или деактивация вызовов ограничений addConstraint: и removeConstraint: в представлении, которое является ближайшим общим предком элементов, управляемых этим ограничением. Используйте это свойство вместо вызова addConstraint: или removeConstraint: напрямую.
Итак, как только у вас есть ссылка strong
на рассматриваемое ограничение (например, у вас есть выход), вы можете просто установить для этого свойства active
значение false
(или NO
в Obj-C) для отключения или true
(или YES
) для включения.
Ответ 3
Соедините Constraint как IBOutlet от раскадровки до ViewController и создайте Array add All constraint в массиве.
Деактивируйте эти ограничения, если они не используются.
Добавить ограничение всякий раз, когда используется.
NSLayoutConstraint *constraint1;
NSLayoutConstraint *constraint2;
NSLayoutConstraint *constraint3;
NSArray *arr = @[constraint1,constraint2,constraint3];
[NSLayoutConstraint deactivateConstraints:arr];
//After deactivate constraint array add what ever frame you want to add
//Activate lateroN
[NSLayoutConstraint activateConstraints:arr];