2015-07-10 2 views
10

Ich habe gerade in Facebook SDK für iOS gesehen, rufen sie [super layoutSubviews]; am ende und nicht am anfang der layoutSubviews-methode. Soweit ich weiß sollten wir es immer als erste Zeile machen. Kann dies zu unerwartetem Verhalten der Benutzeroberfläche führen?Wie lautet die richtige Methode zum Aufrufen von [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

"So weit ich weiß, sollten wir es immer als erste Zeile machen" Woher weißt du das? " – matt

+1

@matt, ich glaube, das ist die Konvention der iOS-Entwickler-Community, da die Super-Klasse einige Standardeinstellungen haben kann, die unser benutzerdefiniertes Layout beeinflussen können (wenn wir es am Ende der Methode tun). Ähnlich wie Super in Konstruktoren/Initializern als erste Zeile aufrufen. – ppalancica

+1

"Die Super-Klasse kann einige Standard/allgemeine Einstellungen haben, die unser benutzerdefiniertes Layout beeinflussen können (wenn wir es am Ende der Methode tun)." Ja, das ist absolut richtig. Aber das ist nicht dasselbe wie "sollte immer". – matt

Antwort

7

Nach dem UIView Class Reference,

Die Standardimplementierung dieser Methode keine Auswirkungen auf iOS 5.1 und früher. Andernfalls verwendet die Standardimplementierung alle Einschränkungen, die Sie festgelegt haben, um die Größe und Position von Unteransichten zu bestimmen.

So dass der Facebook-SDK Beispiel-App [super layoutSubviews] am Ende ihrer Implementierung ruft könnte ein Artefakt der App Wesen zunächst für eine iOS-Version vor iOS 5.1 gebaut sein.

Für neuere Versionen von iOS sollten Sie [super layoutSubviews] zu Beginn Ihrer Implementierung aufrufen. Andernfalls wird die Oberklasse Ihre Unteransichten neu anordnen, nachdem Sie das benutzerdefinierte Layout ausgeführt haben, sodass Ihre Implementierung von "layoutSubviews()" ignoriert wird.

2

Sie müssen immer [super layoutSubviews] zuletzt aufrufen, wenn die inhaltliche Größe einer Ansicht geändert wird. Wenn Sie den Titel der Schaltfläche ändern, wird die inhärente Inhaltsgröße von UIButton geändert, also der letzte Aufruf.

Der erste Aufruf an [super layoutSubviews] ist immer erforderlich, da iOS das Layout basierend auf den Einschränkungen aktualisiert. jedoch die technische korrekteste Art und Weise Ihre Probe sollte der Umsetzung sein:

- (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

Nur neugierig: Ist Ihre Behauptung über die inhaltliche Größe in der Dokumentation überall gesichert? – ndmeiri

+0

Leider nicht, aber wenn Sie darüber nachdenken: Die intrinsische Inhaltsgröße kann nur mit setNeedsLayout aktualisiert werden, was layoutSubviews direkt aufruft. Wenn Sie in LayoutSubviews die inhaltliche Inhaltsgröße ändern (Titel ändern), kann der Container (Button) diese Änderungen nicht korrekt übernehmen, wenn [super layoutSubviews] danach nicht aufgerufen wird. – seeya

+0

@ndmeiri Wenn ich gegen iOS7 lief, habe ich Laufzeitfehler gesehen, wenn ich zuerst [super layoutSubviews] anrufe: App aufgrund der nicht abgefangenen Ausnahme 'NSInternalInconsistencyException' beenden, Grund: 'Auto-Layout ist nach Ausführung von -layoutSubviews noch erforderlich. {VIEW} 's Implementierung von -layoutSubviews muss super aufrufen.' – Matthew

4

Blick in den Code, bevor [super layoutSubviews], es geht nicht um den Rahmen. Also am Ende kann es auch gut funktionieren. Ich schätze, der Coder muss den Titel überprüfen und den Titel anhand einiger Regeln ändern. Er denkt, dass jedes Mal, wenn die layoutSubviews aufgerufen werden, eine gute Gelegenheit ist, diesen Code zu schreiben.