Mam UIView, który jest umieszczony na ekranie z kilkoma ograniczeniami. Właścicielem niektórych ograniczeń jest superview, inne należą do innych przodków (np. Być może właściwość widoku UIViewController).
Chcę usunąć wszystkie te stare ograniczenia i umieścić je w nowym miejscu, używając nowych ograniczeń.
Jak mogę to zrobić bez tworzenia IBOutlet dla każdego pojedynczego ograniczenia i konieczności zapamiętywania, który widok jest właścicielem tego ograniczenia?
Aby rozwinąć, naiwnym podejściem byłoby utworzenie grupy IBOutletów dla każdego z ograniczeń, a następnie wywołanie kodu takiego jak:
[viewA removeConstraint:self.myViewsLeftConstraint];
[viewB removeConstraint:self.myViewsTopConstraint];
[viewB removeConstraint:self.myViewsBottomConstraint];
[self.view removeConstraint:self.myViewsRightConstraint];
Problem z tym kodem polega na tym, że nawet w najprostszym przypadku musiałbym stworzyć 2 IBOutlety. W przypadku złożonych układów może to łatwo osiągnąć 4 lub 8 wymaganych IBOutletów. Ponadto musiałbym upewnić się, że moje wezwanie do usunięcia ograniczenia jest wywoływane z właściwego punktu widzenia. Na przykład wyobraź sobie, że myViewsLeftConstraint
jest własnością viewA
. Gdybym przypadkowo zadzwonił [self.view removeConstraint:self.myViewsLeftConstraint]
, nic by się nie stało.
Uwaga: metoda constraintsAffectingLayoutForAxis wygląda obiecująco, ale jest przeznaczona tylko do debugowania.
Aktualizacja: Wiele odpowiedzi jestem otrzymujących kontrakt z self.constraints
, self.superview.constraints
lub jakiegoś wariantu tych. Te rozwiązania nie będą działać, ponieważ te metody zwracają tylko ograniczenia należące do widoku, a nie te, które mają wpływ na widok.
Aby wyjaśnić problem z tymi rozwiązaniami, rozważ następującą hierarchię widoków:
- Dziadek
- Ojciec
- Mnie
- Syn
- Córka
- Brat
- Mnie
- Wujek
- Ojciec
Teraz wyobraź sobie, że tworzymy następujące ograniczenia i zawsze dołączamy je do ich najbliższego wspólnego przodka:
- C0: Me: ten sam top co Son (należący do mnie)
- C1: Me: width = 100 (należące do mnie)
- C2: Ja: taki sam wzrost jak brat (własność ojca)
- C3: Me: ten sam top co Uncle (właściciel Dziadka)
- C4: Ja: to samo co dziadek (własność dziadka)
- C5: Brat: ten sam lewy co ojciec (własność ojca)
- C6: Wujek: to samo lewe co dziadek (własność dziadka)
- C7: Syn: to samo lewe co córka (należące do mnie)
Teraz wyobraź sobie, że chcemy usunąć wszystkie wpływające ograniczenia Me
. Każde właściwe rozwiązanie powinno usunąć [C0,C1,C2,C3,C4]
i nic więcej.
Jeśli użyję self.constraints
(gdzie jaźń jest mną), dostanę [C0,C1,C7]
, ponieważ są to jedyne ograniczenia, które są moją własnością. Oczywiście nie wystarczyłoby to usunąć, ponieważ go brakuje [C2,C3,C4]
. Ponadto usuwa C7
niepotrzebnie.
Jeśli użyję self.superview.constraints
(gdzie ja jest mną), dostanę [C2,C5]
, ponieważ są to ograniczenia należące do Ojca. Oczywiście nie możemy ich wszystkich usunąć, ponieważ C5
jest to całkowicie niezwiązane z Me
.
Jeśli użyję grandfather.constraints
, dostanę [C3,C4,C6]
. Ponownie, nie możemy ich wszystkich usunąć, ponieważ C6
powinny pozostać nienaruszone.
Podejście brutalnej siły polega na zapętleniu nad każdym z przodków widoku (łącznie z nim samym) i sprawdzeniu, firstItem
czy secondItem
sam widok jest, czy też jest; jeśli tak, usuń to ograniczenie. Doprowadzi to do prawidłowego rozwiązania, powrotu [C0,C1,C2,C3,C4]
i tylko tych ograniczeń.
Mam jednak nadzieję, że istnieje bardziej eleganckie rozwiązanie niż konieczność przeglądania całej listy przodków.