У меня есть UIView, который помещается на экран с помощью нескольких ограничений. Некоторые из ограничений принадлежат супервину, другие принадлежат другим предкам (например, возможно, свойство view UIViewController).
Я хочу удалить все эти старые ограничения и поместить его где-то новым, используя новые ограничения.
Как я могу это сделать, не создавая IBOutlet для каждого отдельного ограничения и не помню, какое представление принадлежит указанному ограничению?
Чтобы разработать, наивный подход заключался бы в создании группы IBOutlets для каждого из ограничений и затем включал бы код вызова, например:
[viewA removeConstraint:self.myViewsLeftConstraint];
[viewB removeConstraint:self.myViewsTopConstraint];
[viewB removeConstraint:self.myViewsBottomConstraint];
[self.view removeConstraint:self.myViewsRightConstraint];
Проблема с этим кодом заключается в том, что даже в простейшем случае мне нужно было бы создать 2 IBOutlets. Для сложных макетов это может легко достичь 4 или 8 требуемых IBOutlets. Кроме того, мне нужно будет убедиться, что мой вызов для удаления ограничения вызывается в правильном представлении. Например, представьте, что myViewsLeftConstraint
принадлежит viewA
. Если бы я случайно вызвал [self.view removeConstraint:self.myViewsLeftConstraint]
, ничего не произошло.
Примечание. Метод constraintsAffectingLayoutForAxis выглядит многообещающим, но предназначен только для целей отладки.
Обновление:. Многие ответы, которые я получаю, имеют дело с self.constraints
, self.superview.constraints
или некоторыми вариантами. Эти решения не будут работать, поскольку эти методы возвращают только ограничения, принадлежащие представлению, а не те, которые влияют на представление.
Чтобы прояснить проблему с этими решениями, рассмотрите эту иерархию представлений:
- Дед
- Отец
- Me
- Сын
- Дочь
- Brother
- Me
- Дядя
- Отец
Теперь представьте, что мы создаем следующие ограничения и всегда присоединяем их к их ближайшему общему предку:
- C0: Me: тот же самый верх, как Сын (принадлежит мне)
- C1: Me: width = 100 (принадлежит мне)
- C2: Me: та же высота, что и брат (принадлежит отцу)
- C3: Me: тот же самый верх, что и дядя (принадлежащий деду).
- C4: Я: тот же самый, что и дедушка (принадлежащий деду).
- C5: Брат: тот же самый, что и Отец (принадлежит отцу)
- C6: Дядя: тот же самый, что и дед (принадлежащий деду).
- C7: Сын: тот же, что и Дочь (принадлежит мне).
Теперь представьте, что мы хотим удалить все ограничения, влияющие на Me
. Любое правильное решение должно удалить [C0,C1,C2,C3,C4]
и ничего больше.
Если я использую self.constraints
(где self is Me), я получу [C0,C1,C7]
, так как это единственные ограничения, которыми владеет Me. Очевидно, этого было бы недостаточно, чтобы удалить это, поскольку отсутствует [C2,C3,C4]
. Кроме того, он ненужно удаляет C7
.
Если я использую self.superview.constraints
(где self is Me), я получу [C2,C5]
, так как это ограничения, принадлежащие Отцу. Очевидно, мы не можем удалить все это, так как C5
полностью не связано с Me
.
Если я использую grandfather.constraints
, я получу [C3,C4,C6]
. Опять же, мы не можем удалить все из них, так как C6
должен оставаться неповрежденным.
Подход грубой силы состоит в том, чтобы зацикливать каждого из предков предков (включая себя) и увидеть, является ли firstItem
или secondItem
самим представлением; если это так, удалите это ограничение. Это приведет к правильному решению, возвращая [C0,C1,C2,C3,C4]
и только эти ограничения.
Однако я надеюсь, что есть более элегантное решение, чем необходимость перебирать весь список предков.