Widzę różne przykłady, w których ustawiane są ograniczenia. Niektórzy ustawiali je w viewDidLoad
/ loadView
(po dodaniu widoku podrzędnego). Inni ustawiają je w metodzie updateViewConstraints
, która jest wywoływana przez viewDidAppear
.
Kiedy próbuję ustawić ograniczenia updateViewContraints
, układ może być niespójny, np. Niewielkie opóźnienie przed pojawieniem się widoku. Ponadto, jeśli używam tej metody, czy powinienem najpierw usunąć istniejące ograniczenia, tj. [self.view [removeConstraints:self.view.constraints]
?
ios
cocoa-touch
autolayout
Heisenberg
źródło
źródło
updateViewConstraints
: Możesz nadpisać tę metodę w podklasie, aby dodać ograniczenia do widoku lub jego widoków podrzędnych. (z dokumentacji Apple )Odpowiedzi:
Skonfigurowałem moje ograniczenia w
viewDidLoad
/loadView
(celuję w iOS> = 6).updateViewConstraints
przydaje się do zmiany wartości ograniczeń, np. jeśli jakieś ograniczenie jest zależne od orientacji ekranu (wiem, to zła praktyka) to można to zmienićconstant
w tej metodzie.Dodawanie ograniczeń w programie
viewDidLoad
jest pokazane podczas sesji „Wprowadzenie do automatycznego układu dla iOS i OS X” (WWDC 2012), począwszy od 39:22. Myślę, że to jedna z tych rzeczy, o których mówi się na wykładach, ale nie ląduje w dokumentacji.AKTUALIZACJA: Zauważyłem wzmiankę o ustawianiu ograniczeń w zarządzaniu zasobami w kontrolerach widoku :
UPDATE 2 : Podczas WWDC 2015 Jabłko dał nową wyjaśnienie z
updateConstraints
iupdateViewConstraints
Zalecane użycie:źródło
@"|-[button1]-[button2]-|"
w ViewController, prawda? Czy jest inny sposób?updateViewConstraints
?Zalecam utworzenie BOOL i ustawienie ich w
-updateConstraints
UIView (lub-updateViewConstraints
, dla UIViewController).-[UIView updateConstraints]
: (apple docs)Oba
-updateConstraints
i-updateViewConstraints
mogą być wywoływane wiele razy w trakcie trwania widoku. (Na przykład wywołaniesetNeedsUpdateConstraints
widoku spowoduje to, że tak się stanie). W rezultacie musisz upewnić się, że nie tworzysz i nie aktywujesz powielonych ograniczeń - albo używając BOOL, aby wykonać tylko określoną konfigurację ograniczenia, albo upewniając się, że dezaktywować / usunąć istniejące ograniczenia przed utworzeniem i aktywacją nowych.Na przykład:
- (void)updateConstraints { // for view controllers, use -updateViewConstraints if (!_hasLoadedConstraints) { _hasLoadedConstraints = YES; // create your constraints } [super updateConstraints]; }
Pozdrawiam @fresidue w komentarzach za wskazanie, że dokumentacja Apple zaleca dzwonienie
super
jako ostatni krok. Jeśli wywołaszsuper
przed wprowadzeniem zmian w niektórych ograniczeniach, możesz napotkać wyjątek czasu wykonywania (awarię).źródło
-updateConstraints
ani niczego - nadal byłby wywoływany, a ty nadal dzwonisz[super updateConstraints]
.super
na samym końcu implementację-updateConstraints
lub-updateViewConstraints
. Zobacz ten komentarz, aby uzyskać więcej informacji.Należy to zrobić w ViewDidLoad, zgodnie z filmem WWDC firmy Apple i dokumentacją.
Nie mam pojęcia, dlaczego ludzie polecają updateConstraints. Jeśli zrobisz to w updateConstraints, napotkasz problemy z NSAutoresizingMaskLayoutConstraint z automatyczną zmianą rozmiaru, ponieważ Twoje widoki uwzględniły już automatyczne maski. Aby działało, musisz je usunąć w updateConstraints.
UpdateConstraints powinny służyć właśnie do tego, gdy musisz je „zaktualizować”, wprowadzić zmiany itp. Od początkowej konfiguracji.
źródło
Zrób to na widoku podwidoków układu
override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() }
źródło
Mam to rozwiązanie, aby zmienić ograniczenia, zanim ci, którzy są w storyboardzie, zostaną załadowani. To rozwiązanie usuwa wszelkie opóźnienia po załadowaniu widoku.
-(void)updateViewConstraints{ dispatch_async(dispatch_get_main_queue(), ^{ //Modify here your Constraint -> Activate the new constraint and deactivate the old one self.yourContraintA.active = true; self.yourContraintB.active= false; //ecc.. }); [super updateViewConstraints]; // This must be the last thing that you do here -> if! ->Crash! }
źródło
Możesz je ustawić w viewWillLayoutSubviews: too:
override func viewWillLayoutSubviews() { if(!wasViewLoaded){ wasViewLoaded = true //update constraint //also maybe add a subview } }
źródło
To zadziałało dla mnie:
Swift 4.2
override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) // Modify your constraints in here ... }
Chociaż szczerze nie jestem pewien, czy warto. Wydaje się, że ładuje się nieco wolniej niż w viewDidLoad (). Chciałem tylko usunąć je z tego ostatniego, ponieważ robi się ogromne.
źródło
Poniższy przykład to przekazanie dowolnego widoku innej klasie. stworzyć mój widok z storyboardu
Swift 5.0
override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) DispatchQueue.main.async { self.abcInstance = ABC(frame: self.myView.frame) } }
źródło