2016-07-21 13 views
6

An mehreren Stellen in meiner Anwendung bekomme ich null Rahmengrößen, wo ich einen Rahmen bekommen habe. Dies hat mich besonders betroffen, wenn ich runde Objekte mit einem cornerRadius von size/2 erstellt habe.Xcode 8 legt die Bildgröße unterschiedlich fest. Wie finde ich weitere Details?

Zum Beispiel in Xcode 7 das hat gut funktioniert:

class AvatarUIButton: UIButton { 
    required init?(coder aDecoder: NSCoder) { 
    super.init(coder: aDecoder) 
    layer.masksToBounds = true 
    layer.cornerRadius = bounds.size.width/2 
    } 
} 

Aber jetzt in Xcode 8 Ich habe dies zu tun:

class AvatarUIButton: UIButton { 
    override var bounds: CGRect { didSet { 
    layer.cornerRadius = bounds.size.width/2 
    }} 

    required init?(coder aDecoder: NSCoder) { 
    super.init(coder: aDecoder) 
    self.layer.masksToBounds = true 
    } 
} 

In diesem Beispiel ist die Veränderung wohl besser/offensichtlich. Ich habe eine andere Situation, die viel weniger isoliert ist mit einem 0 Frame auf TableHeaderView, die nur für xcode 8 ist.

Ich bin auf der Suche nach Release Notes, Mailingliste Diskussion oder ähnliches, die eine Änderung in der Reihenfolge der Bestimmung der Rahmengröße diskutiert damit ich herausfinden kann, was sich geändert hat und wie ich es beheben kann.

+0

ich bin mit dem gleichen Problem. Es ist ein AutoLayout-Problem. In meinem Fall protokollieren Frames als (0, 0, 1000, 1000). Wenn Sie den Eckenradius auf einen festen Wert setzen (nicht berechnet), wird die Ansicht erneut angezeigt. Ohne AutoLayout existiert das Problem nicht. – Tuslareb

+0

Ich hatte ein ähnliches Problem mit einer Unteransicht in einer benutzerdefinierten Tabellenzelle. Die Unteransicht enthielt Einschränkungen für Position und Größe. Bevor die Zelle angezeigt wurde, war der Rahmen für diese Unteransicht {(0,0), (1000,1000)}. Benutzerdefinierte Zeichnung basierend auf diesem Rahmen funktionierte eindeutig nicht. Beim Debuggen und Überprüfen der Ansichten habe ich festgestellt, dass der Frame erst nach dem Rendern der Ansicht korrekt war. Meine Lösung war, '[cell layoutIfNeeded]' direkt nach dem Herausnehmen der Zelle in 'cellForRowAtIndexPath:' hinzuzufügen. Es löste das Problem für mich und ich konnte den Eckenradius woanders berechnen. –

+0

gelernt: ja, Frames haben 1000 oder Null Größe in 'ViewWillAppear' jetzt (abhängig davon, welche xcode Beta Sie haben). Aber in 'viewWillAppear' können Sie' view.layoutIfNeeded() 'aufrufen, um Ihre Frames korrekt zu skalieren. – SimplGy

Antwort

2

In Xcode 8, Apfel sagen:

Xcode 8 die Fähigkeit entfernt Ansichten ohne Einschränkungen zu konfigurieren mit Rahmen pro Größenklasse variieren. Ansichten ohne Einschränkungen können nach dem Kompilieren mit Xcode 8 beim Umstellen von Größenklassen unter Laufzeit abweichen. Verwenden Sie in Zukunft Constraints und Autoresizing-Masken mit der Geräteleiste , um das gewünschte Layout zu erreichen. (25894544)

In früheren Versionen von Xcode haben wir das Design auf dem ViewDidLoad definiert. Aber hier wurden die verschiedenen Elemente nicht erstellt (und auch Einschränkungen), sodass die Ansicht mit der Größe im Storyboard erstellt wurde.

Jetzt, in Xcode 8, können wir es nicht mehr tun. Wir müssen Beschränkungen haben, weil der Rahmen nicht initialisiert wird (deshalb haben einige von Ihnen diese Werte für die Rahmengröße: 0, 0, 1000, 1000). Zum Beispiel, machen Sie es in der ViewDidAppear und es wird gut funktionieren. Aber Sie werden zuerst Ihren Knopf ohne Eckenradius einige Male sehen.

Also, was können Sie tun, ist diese Funktion nutzen (hier in Objective C) (wo Sie wollen, auch in der Ladefunktion):

[self performSelector:@selector(setCornerToMyButton) withObject:NULL afterDelay:0]; 

Sie können pu die Verzögerung Sie wollen, aber auch mit 0 funktioniert es.

Und Ihr Radius zum Beispiel wie folgt in dieser Funktion ändern:

- (void) setCornerToMyButton { 
    //Do what you want... 
    layer.masksToBounds = true 
    layer.cornerRadius = bounds.size.width/2 
} 

Hope this Ihnen helfen.

+1

Größe nicht in 'ViewDidLoad', ich glaube nicht, dass Frame-Größen garantiert. Ich benutze 'viewWillAppear', irgendeinen Einblick darauf? Ich dachte, Frames würden bis dahin Größe sein (nicht "viewDidLoad"), aber sie sind nicht in xcode 8. Die Dimensionierung auf "viewDidAppear" verursacht Layout-Verschiebung wie Sie bemerken, so dass das nicht akzeptabel ist. Die Verwendung einer Verzögerung scheint inkorrekt/hacky zu sein, obwohl ich dir vertraue, dass es funktioniert. Ich denke, die Plattform sollte ein "bereit zu legen" -Event haben. Ich dachte, das wäre 'viewWillAppear'. – SimplGy

+0

Wenn Sie die Aktualisierung im nächsten Frame erzwingen wollen, verwenden Sie einfach 'dispatch_async (dispatch_get_main_queue(), {})' anstelle von 'performSelector: withObject: afterDelay:'. Ich denke "performSelector" ist ziemlich albern, besonders in swift. – MrJre

2

in Ihrem Fall rufen Sie einfach:

override func draw(_ rect: CGRect) { 
    self.layoutIfNeeded() 
    layer.masksToBounds = true 
    layer.cornerRadius = bounds.size.width/2 
} 

für einen UIViewController einfach anrufen view.layoutIfNeed() direkt nach dem Super.viewDidLoad(), es funktioniert wie ein Charme; ich weiß nicht, was die Ursache dieses Problems (wenn es ein Problem ist), so scheint es, dass das Laden der Ansicht nicht "layout" die Ansicht nicht mehr mit Autoresize oder Autolayout für diese Angelegenheit, so wie ich für die Zeit Sie sagte kann diese Lösung verwenden, bis wir ein besseres Verständnis darüber haben, was genau auch für benutzerdefinierte Klassen geändert hat (benutzerdefinierte Schaltfläche für Beispiel) Sie können layoutSubviews() oder layoutIfNeeded() überschreiben, dort finden Sie den Rahmen/das Layout, die Sie suchen und anwenden was Änderungen

0

wollen bekam ich die Antwort gerade jetzt

[super viewDidLoad]; 
[self.myNeedFrameView layoutIfNeeded]; 
+2

Können Sie erklären, wo dieser Code in Bezug auf die ursprüngliche Frage hinzugefügt wird. Wenn möglich, auch "warum" behebt es das Problem? – Jmons

+0

Willkommen bei Stack Overflow! Während dieses Code-Snippet das Problem lösen kann, erklärt es nicht, warum oder wie es die Frage beantwortet. Bitte [fügen Sie eine Erklärung für Ihren Code hinzu] (// meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers), da dies wirklich zur Verbesserung der Qualität Ihres Posts beiträgt. Denken Sie daran, dass Sie die Frage für Leser in der Zukunft beantworten, und diese Leute könnten die Gründe für Ihren Codevorschlag nicht kennen. ** Flaggers/Rezensenten: ** [Für Code-only Antworten wie diese, Downvote, nicht löschen!] (// meta.stackoverflow.com/a/260413/2747593) –

+0

Ich verstehe die Antwort, aber es trifft nicht auf diese genaue Frage zu. Da dies eine UIView anzeigt, gibt es keinen 'viewDidLoad'-Hook. @DanielBarbarian ist korrekt, dass dieses Problem auch für View-Controller gilt, und dass dies in diesem Fall eine Fehlerbehebung ist. – SimplGy