2014-10-22 21 views
16

Wcześniej muszę powiedzieć, że faktycznie uzyskałem widoczny efekt, którego pragnąłem, ale nie w zadowalający sposób, ponieważ teraz, ograniczenia muszą być "zerwane" zamiast być odpowiednio zaktualizowanym.Widok nie aktualizuje się po automatycznej zmianie ograniczeń automatycznego układu.

Mam ViewController, który posiada UITableView. Wysokość tego tableView może być różna od 0 (niewidoczna) do dowolnej liczby przechowywanych wierszy. Wysokość jest obliczana w viewDidLoad obiektu ViewController przez pomnożenie bieżącej liczby wierszy przez wysokość wiersza.

Pierwszą rzeczą, którą próbowałem, było stworzenie @IBOutlet weak var tableHeightConstraint: NSLayoutConstraint! połączonego z zestawem ograniczeń wysokości w scenorysie. Ma tylko kilka losowych wysokość początkową, ale to jest aktualizowany do prawidłowej wartości w ViewController na viewDidLoad() następnie metodą, która uaktualnia widok, jeśli potrzebne:

tableHeightConstraint = NSLayoutConstraint(item: tableView, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 0, constant: calculatedTableViewHeight) 

// At this point I've tried a variety of methods like the following two but actually none has worked for me 
view.layoutIfNeeded() 

// or 
view.updateConstraints() 

// or 
view.layoutSubviews() 

... i nawet te same metody na Tableview po prostu mieć pewność, jak również umieszczenie tych wszystkich w viewDidLayoutSubviews().

Więc próbowałem następnie stworzyć takie samo ograniczenie jak powyżej, ale zamiast aktualizowania po prostu dodałem go do widoku: view.addConstraint(tableHeightConstraint). To faktycznie miało pożądany efekt wizualny, ale w dziennikach pojawił się konflikt tych dwóch ograniczeń wysokości, co spowodowało przerwanie początkowego. Ponieważ moim celem jest uzyskanie poprawnego i czystego kodu, próbowałem dalej. Tym razem najpierw usunąłem wiązanie z widoku przed ponownym dodaniem skorygowanego. Wizualnie, znowu wszystko było idealne, ale wciąż nie pozbywałem się sprzecznych ograniczeń.

Moje pytanie brzmi (poza tym, co robiłem źle do tej pory), jak mogę - najlepiej - zaktualizować istniejące ograniczenie, a następnie odpowiednią aktualizację/przekazanie widoku i jego podstron w dowolnym punkcie, niezależnie od tego, czy kiedy po raz pierwszy ładuję widok lub chcę zmienić niektóre więzy, gdy użytkownik wchodzi w interakcje. Wielkie dzięki za pomoc!

+0

Ustawienie właściwości na nowe wiązanie nie usuwa starej, po prostu powoduje, że wskaźnik wskazuje nowy, dlatego pojawiają się sprzeczne ograniczenia. Powinieneś to zrobić tak, jak w odpowiedzi @mmyr. – rdelmar

+0

@rdelmar Ok, rozumiem, dzięki za wyjaśnienie! Ale dlaczego nadal istniał konflikt podczas przechodzenia do 'view.removeConstraint (tableHeightConstraint)', generując nowy i dodając go ponownie do widoku przez view.addConstraint (tableHeightConstraint) '? Dla zrozumienia powodów ... –

+1

Co to jest widok w tym stwierdzeniu? Czy jest to self.view kontrolera? Ograniczenie wysokości, które tworzysz w scenorysie, dodawane jest do widoku, w którym ustawiasz wysokość widoku tabeli w twoim przypadku (nie w superwizorze). Czy próbowałeś, self.tableView.removeConstraint (tableHeightConstraint)? Nowa powinna również zostać dodana do widoku tabeli. – rdelmar

Odpowiedz

29

Obecnie przypisujesz nowe ograniczenie, zamiast aktualizować bieżące. Nowe ograniczenie również nie zostało dodane do hierarchii widoku.

Twoje podejście z użyciem IBOutlet odwołać ograniczenie skonfigurować w IB to dobre podejście, ale zamiast przypisywania nowego ograniczenia do tego var, wystarczy zmodyfikować ograniczenie stałą:

tableHeightConstraint.constant = calculatedTableHeight.

Nie trzeba wywoływać tutaj układu layoutIfNeeded(), ponieważ ograniczenia obsługują wywoływanie układu automatycznie po zmianie ich stałych. updateConstraints() i layoutSubviews() zdecydowanie nie są tym, czego potrzebujesz.

+0

Naprawdę chciałbym móc po prostu zmienić wskaźnik, aby odwoływał się do innego ograniczenia, aby bardziej elegancko przełączać się pomiędzy 2 trybami. Ale nie wydaje się, aby jakikolwiek komunikat aktualizacji spowodował, że nowo powołane ograniczenie zastąpi poprzednią. Czy utknąłem z konieczności dodawania i usuwania ograniczeń, o których mowa, za każdym razem, gdy chcę zmienić tryby? – Michael

+0

@Michael: odniesienie, które trzymasz w ograniczeniu, jest przeznaczone na własny użytek; jeśli dodasz ograniczenie do widoku i nie zapisujesz odnośnika w dowolnym miejscu, to jest ono nadal dodawane do widoku. – cmyr

+0

Tak, to ma sens; łatwiej zrozumieć, gdy myślisz o ograniczeniach na widoku po prostu jako zestaw elementów. Ograniczenie XIB powiązane z IBOutlet jest tylko sposobem inicjowania ograniczenia i dodania go do tablicy przy pierwszym obciążeniu. Zmiana wskaźnika w kontrolerze nie zmienia tego, co już jest w macierzy, podczas gdy zmiana właściwości na wiązaniu (tj. Stała) zmienia wartość i ma rzeczywisty efekt. – Michael

Powiązane problemy