2015-07-10 9 views
10

Właśnie widziałem w Facebook SDK dla iOS, nazywają [super layoutSubviews]; na końcu, a nie na początku metody layoutSubviews. O ile mi wiadomo, powinniśmy zawsze robić to jako pierwszą linię. Czy to może spowodować nieoczekiwane zachowanie interfejsu użytkownika?Jaki jest prawidłowy sposób wywoływania [super layoutSubviews]?

- (void)layoutSubviews 
{ 
    CGSize size = self.bounds.size; 
    CGSize longTitleSize = [self sizeThatFits:size title:[self _longLogInTitle]]; 
    NSString *title = (longTitleSize.width <= size.width ? 
        [self _longLogInTitle] : 
        [self _shortLogInTitle]); 
    if (![title isEqualToString:[self titleForState:UIControlStateNormal]]) { 
    [self setTitle:title forState:UIControlStateNormal]; 
    } 

    [super layoutSubviews]; 
} 
+0

"O ile mi wiadomo, powinniśmy zawsze robić to jako pierwszą linię" Jak to "wiedzieć"? – matt

+1

@matt, uważam, że jest to konwencja, którą społeczność programistów iOS używa jako super-klasy, może mieć pewne ustawienia domyślne/ogólne, które mogą wpływać na nasz niestandardowy układ, który nie ma zastosowania (jeśli zrobimy to na końcu metody). Podobnie jak wywołanie super w konstruktorach/inicjalizatorach jako pierwszej linii. – ppalancica

+1

"super-klasa może mieć pewne ustawienia domyślne/ogólne, które mogą wpłynąć na nasz niestandardowy układ, który nie ma zastosowania (jeśli zrobimy to na końcu metody)." Tak, to absolutnie prawda. Ale to nie to samo, co "zawsze powinno". – matt

Odpowiedz

7

Według UIView Class Reference,

Domyślna implementacja tej metody nie robi nic na iOS 5.1 i wcześniejszych. W przeciwnym razie domyślna implementacja używa dowolnych ograniczeń, które ustawiłeś, aby określić rozmiar i pozycję dowolnych subskrybentów.

zatem, że przykład aplikacja Facebook SDK wzywa [super layoutSubviews] po zakończeniu ich realizacji może być artefaktem app istoty pierwotnie zbudowany dla wersji iOS przed iOS 5.1.

W przypadku nowszych wersji iOS należy wywołać [super layoutSubviews] na początku swojej implementacji. W przeciwnym razie superklasa zmieni układ subskrybentów po wykonaniu niestandardowego układu, skutecznie ignorując implementację "layoutSubviews()".

2

Musisz zawsze zadzwonić pod numer [super layoutSubviews], jeśli rozmiar zawartości wewnętrznej widoku zostanie zmieniony. Jeśli zmienisz tytuł przycisku, zmieniony zostanie rozmiar zawartości wewnętrznej UIButton, czyli ostatniego połączenia.

Pierwsze wywołanie [super layoutSubviews] jest zawsze wymagane, ponieważ system iOS aktualizuje układ na podstawie ograniczeń. Jednak techniczny najbardziej poprawny sposób wdrożenia swoje próbki powinny być:

- (void)layoutSubviews 
{ 
[super layoutSubviews]; 
    CGSize size = self.bounds.size; 
    CGSize longTitleSize = [self sizeThatFits:size title:[self _longLogInTitle]]; 
    NSString *title = (longTitleSize.width <= size.width ? 
        [self _longLogInTitle] : 
        [self _shortLogInTitle]); 
    if (![title isEqualToString:[self titleForState:UIControlStateNormal]]) { 
    [self setTitle:title forState:UIControlStateNormal]; 
    } 

    [super layoutSubviews]; 
} 
+0

Po prostu ciekawy: czy Twoje twierdzenie o wewnętrznym rozmiarze treści jest zapisane w dokumentacji w dowolnym miejscu? – ndmeiri

+0

Niestety nie, ale jeśli myślisz o tym: Wewnętrzny rozmiar treści można zaktualizować tylko za pomocą setNeedsLayout, który bezpośrednio wywołuje layoutSubviews. Jeśli zmienisz rozmiar wewnętrznej treści (tytuł przycisku zmiany) w layoucieSubinów, kontener (Przycisk) nie może zastosować tych zmian poprawnie, jeśli [super layoutSubviews] nie zostanie wywołane później. – seeya

+0

@ndmeiri Podczas pracy z iOS7 widziałem błędy środowiska wykonawczego, jeśli najpierw wywołuję tylko [super layoutSubviews]: kończenie aplikacji z powodu nieprzechwyconego wyjątku "NSInternalInconsistencyException", powód: "Auto Layout nadal wymagany po wykonaniu -layoutSubviews. {VIEW} w implementacji -layoutSubviews wymaga połączenia super. ' – Matthew

4

spojrzenie na kod, zanim [SUPER layoutSubviews], to nie chodzi o ramy. więc umieścić go na końcu może również dobrze. Domyślam się, że programista musi chcieć sprawdzić tytuł i zmodyfikować tytuł na podstawie pewnych reguł, myśli za każdym razem, gdy wywołanie layoutSubviews jest odpowiednią okazją, aby to zrobić, więc wstawił tutaj kod.