setNeedsLayout vs. setNeedsUpdateConstraints i layoutIfNeeded vs updateConstraintsIfNeeded
Wiem, że łańcuch układu auto składa się w zasadzie z 3 różnych procesów.
- Aktualizacja ograniczeń
- widoki układu (tutaj otrzymujemy obliczenia ramek)
- wyświetlacz
To, co nie jest dla mnie do końca jasne, to wewnętrzna różnica między -setNeedsLayout
i -setNeedsUpdateConstraints
. Z Apple Docs:
SetNeedsLayout
Wywołaj tę metodę w głównym wątku aplikacji, Jeśli chcesz Dostosuj układ podglądów podglądu. Metoda ta zwraca uwagę na wniosek i zwraca natychmiast. Ponieważ metoda ta nie Wymuś natychmiastową aktualizację, ale zamiast tego czeka na następną aktualizację cyklu, można go użyć do unieważnienia układu wielu widoków zanim któryś z tych widoków zostanie zaktualizowany. To zachowanie pozwala na skonsoliduj wszystkie aktualizacje układu w jednym cyklu aktualizacji, który jest zwykle lepiej dla wydajności.
SetNeedsUpdateConstraints
Gdy właściwość widoku niestandardowego zmieni się w sposób, który wpłynie ograniczenia, można wywołać tę metodę, aby wskazać, że ograniczenia muszą być aktualizowane w pewnym momencie w przyszłości. System będzie wtedy wywołanie updateConstraints jako część jego normalnego przebiegu układu. Aktualizacja ograniczenia wszystkie naraz tuż przed ich potrzebą zapewnia, że nie niepotrzebnie przeliczać ograniczeń, gdy wiele zmian to wykonane do widoku pomiędzy przejściami układu.
Gdy chcę animować Widok po modyfikacji ograniczenia i animować zmiany, które zwykle wywołuję na przykład:
[UIView animateWithDuration:1.0f delay:0.0f usingSpringWithDamping:0.5f initialSpringVelocity:1 options:UIViewAnimationOptionCurveEaseInOut animations:^{
[self.modifConstrView setNeedsUpdateConstraints];
[self.modifConstrView layoutIfNeeded];
} completion:NULL];
Dowiedziałem się, że jeśli użyję -setNeedsLayout
zamiast -setNeedsUpdateConstraints
Wszystko działa zgodnie z oczekiwaniami, ale jeśli zmienię -layoutIfNeeded
na -updateConstraintsIfNeeded
, animacja nie nastąpi.
Próbowałem wyciągnąć własne wnioski:
-
-updateConstraintsIfNeeded
tylko zaktualizuj ograniczenia, ale nie wymusza wchodzenia w układ proces, dzięki czemu Oryginalne ramki są nadal zachowane -
-setNeedsLayout
wywołuje również metodę-updateContraints
Więc kiedy można używać jednego zamiast drugiego? a jeśli chodzi o metody układu, Czy muszę je wywoływać w widoku, który ma zmianę ograniczenia, czy w widoku nadrzędnym?
2 answers
Twoje wnioski są słuszne. podstawowy schemat to:
-
setNeedsUpdateConstraints
zapewnia przyszłe połączenie doupdateConstraintsIfNeeded
połączeńupdateConstraints
. -
setNeedsLayout
zapewnia przyszłe połączenie dolayoutIfNeeded
połączeńlayoutSubviews
.
Kiedy layoutSubviews
jest wywołana, również wywołuje updateConstraintsIfNeeded
, więc ręczne wywołanie jest rzadko potrzebne w moim doświadczeniu. W rzeczywistości nigdy go nie wywołałem, z wyjątkiem debugowania układów.
Aktualizowanie ograniczeń za pomocą setNeedsUpdateConstraints
jest również dość rzadkie, objc. io-a MUSI przeczytać o autolayouts-says :
Jeśli później coś się zmieni, co unieważnia jedno z ograniczeń, należy natychmiast usunąć ograniczenie i wywołać setNeedsUpdateConstraints. w rzeczywistości jest to jedyny przypadek, w którym należy uruchomić przepustkę aktualizacji ograniczenia.
Ponadto, z mojego doświadczenia, nigdy nie musiałem unieważniać ograniczeń i nie ustawiać setNeedsLayout
w następnej linii kodu, ponieważ nowe ograniczenia w zasadzie proszą o nowy layout.
Zasady są następujące:
- jeśli manipulowałeś ograniczeniami bezpośrednio, zadzwoń
setNeedsLayout
. - jeśli zmienisz pewne warunki (takie jak offsety lub smth), które zmienią ograniczenia w Twojej nadpisanej metodzie
updateConstraints
(zalecany sposób zmiany ograniczeń, btw), wywołajsetNeedsUpdateConstraints
, a przez większość czasusetNeedsLayout
później. - jeśli potrzebujesz którejś z powyższych czynności, aby uzyskać natychmiastowy efekt-np. gdy musisz nauczyć się nowej wysokości klatki po layout pass-dodaj go za pomocą
layoutIfNeeded
.
Również, w Twoim kodzie animacji, uważam, że {[0] } jest niepotrzebny, ponieważ ograniczenia są aktualizowane przed animacją ręcznie, a animacja tylko odtwarza widok na podstawie różnic między starymi i nowymi.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-27 15:44:40
Odpowiedź coverbacka jest całkiem poprawna . Chciałbym jednak dodać kilka dodatkowych szczegółów.
Poniżej znajduje się schemat typowego cyklu UIView, który wyjaśnia inne zachowania
- dowiedziałem się, że jeśli użyję-setNeedsLayout zamiast-setNeedsUpdateConstraints wszystko działa zgodnie z oczekiwaniami, ale jeśli zmienię-layoutIfNeeded z-updateConstraintsIfNeeded, animacja nie nastąpi.
updateConstraints
zazwyczaj nie robi cokolwiek. Po prostu rozwiązuje ograniczenia, nie stosuje ich do momentu wywołania layoutSubviews
. Tak więc animacja wymaga wywołania layoutSubviews
.
- również wywołania setNeedsLayout-metoda updateContraints
updateConstraints
. Musisz jawnie wywołać setNeedsUpdateConstraint
, aby zmodyfikować ograniczenia w procesie.
Aby zadzwonić updateConstraints
należy wykonać następujące czynności:
[view setNeedsUpdateConstraints];
[view setNeedsLayout];
[view layoutIfNeeded];
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-22 17:12:15