Jaka jest różnica między tymi wszystkimi metodami automatycznej aktualizacji układu? Czy wszystko jest konieczne?

W poniższym kodzie, te cztery metody są wywoływane do rozumowania układu. Jestem trochę zdezorientowany, dlaczego wszystkie są potrzebne, chociaż, i co robią inaczej od siebie. Są one używane w procesie, aby wysokość komórki była dynamiczna z automatycznym układem. (Zaczerpnięte z tego repozytorium z tego pytania.)

[cell setNeedsUpdateConstraints];
[cell updateConstraintsIfNeeded];
[cell.contentView setNeedsLayout];
[cell.contentView layoutIfNeeded];

I to z tego bloku kodu na wysokość komórki:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{

    RJTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    [cell updateFonts];

    NSDictionary *dataSourceItem = [self.model.dataSource objectAtIndex:indexPath.row];
    cell.titleLabel.text =  [dataSourceItem valueForKey:@"title"];
    cell.bodyLabel.text = [dataSourceItem valueForKey:@"body"];

    cell.bodyLabel.preferredMaxLayoutWidth = tableView.bounds.size.width - (kLabelHorizontalInsets * 2.0f);

    [cell setNeedsUpdateConstraints];
    [cell updateConstraintsIfNeeded];
    [cell.contentView setNeedsLayout];
    [cell.contentView layoutIfNeeded];

    CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;

    return height;
}
Ale co oni robią inaczej? Dlaczego wszystkie są potrzebne?
Author: Community, 0000-00-00

1 answers

Układ

Załóżmy, że zamkniesz swoją logikę widoku w UIView podklasie i nazwiesz ją SomeView. Oznacza to, że SomeView powinien wiedzieć, jak sam układ , czyli jak umieszczać w nim inne widoki (można również utworzyć widok, który sam się rysuje bez użycia podwidłów, ale to wykracza poza potrzeby przeciętnego dewelopera).

Ten układ jest wykonywany przez [SomeView layoutSubviews]. Masz możliwość nadpisania:

subview.frame = CGRectMake(100 + shiftX, 50 + shiftY, 250 + shiftX - paddingRight, ...
// Oh no, I think I didn't do it right.
Ale rzadko trzeba to robić. In the dark wiek Cocoa Touch, ten ręczny układ był rozpowszechniony, ale teraz powiedziałbym, że 99% układów może być objętych układem automatycznym.

System musi wiedzieć, kiedy powinien zadzwonić [UIView layoutSubviews]. Oczywiście robi się to za pierwszym razem, gdy musisz narysować widok, ale może być również wywoływany za każdym razem, gdy zmienia się ramka superview. Oto szczegółowe wyjaśnienie.

Więc system często wywołuje [view layoutIfNeeded]. Możesz również zadzwonić w dowolnym momencie, ale będzie to miało wpływ tylko wtedy, gdy istnieje jakieś zdarzenie, które wywołało [view setNeedsLayout] lub jeśli wywołałeś je ręcznie, jak w tym przypadku.

Układ Automatyczny (pisany wielkimi literami w dokumentacja) nazywa się tak, ponieważ zostawiasz [SomeView layoutSubviews] tak, jak jest dziedziczony z UIView i zamiast tego opisz pozycję swoich podwinięć w kategoriach ograniczeń .

Podczas używania układu automatycznego, system będzie wykonywał wywołania [view updateConstraintsIfNeeded] przy każdym przebiegu układu. Jednakże, tylko jeśli ustawiony jest znacznik [view setNeedsUpdateConstraints];, metoda wywoła do -updateConstraints (która wykonuje rzeczywiste zadanie).

Jeśli nie używasz układu automatycznego, te metody nie są istotne.

Możesz zaimplementować to tak jak w tym przykładzie .

Twój przykład

Rzadko jest konieczne bezpośrednie wywołanie -layoutIfNeeded i -updateConstraintsIfNeeded, ponieważ silnik interfejsu użytkownika zrobi to automatycznie przy każdym przejściu układu. Jednak w tym przypadku autor zdecydował się na ich natychmiastowe wywołanie; dzieje się tak dlatego, że wynikające wysokość jest potrzebna teraz, a nie w przyszłości.

Ta metoda aktualizacji wysokości komórki wydaje się odpowiednia. Zauważ, że cell może być nowo utworzoną komórką, a zatem nie jest jeszcze dodana do hierarchii widoku; nie ma to wpływu na jej zdolność do układania się.

Podsumowanie

W widoku niestandardowym wybierz następujące opcje, zaczynając od najbardziej "uniwersalnej" do najbardziej "dostosowanej":

  1. Tworzenie ograniczeń podczas tworzenia widoku (ręcznie lub w IB)
  2. jeśli chcesz zmienić ograniczenia później, obejdź -updateConstraints.
  3. jeśli mają złożony układ, którego nie można opisać za pomocą powyższych środków, Nadpisz -layoutSubviews.

W kodzie, który zmienia coś, co może zmienić ograniczenia twojego widoku, wywołaj

[view setNeedsUpdateConstraints];

Jeśli potrzebujesz wyników natychmiast, zadzwoń również

[view updateConstraintsIfNeeded]; 

Jeśli kod zmieni ramkę widoku użyj

[view setNeedsLayout]; 

I wreszcie, jeśli chcesz natychmiast uzyskać wyniki, call

[view layoutIfNeeded];

Dlatego wszystkie cztery wywołania są wymagane w tym przypadku.

Materiały dodatkowe

Spójrz na szczegółowe wyjaśnienie w artykule Advanced Auto Layout Toolbox, objc.io wydanie #3

 45
Author: Honey,
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
2017-10-17 14:33:53