2012-12-19 11 views
9

Ich habe einige Probleme mit NSLayoutConstraint.Hinzufügen und Einstellen NSLayoutConstraint über Code

NSLayoutConstraint gibt mir eine Ausnahme, wenn ich versuche, constant mit der setConstant: Methode zu ändern. Ich habe nur dieses Problem, wenn ich die Höhenbeschränkung über Code hinzufüge.

Zunächst einmal, ich bin immer die Höhe Einschränkung wie so:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"firstAttribute = %d", NSLayoutAttributeWidth]; 
NSArray *filteredArray = [[self constraints] filteredArrayUsingPredicate:predicate]; 
return filteredArray[0]; 

Was mir die richtige Einschränkung gibt. Ich habe eine NSTextField-Unterklasse, wo dies perfekt funktioniert. Die Einschränkungen werden im Interface Builder festgelegt, und ich kann die Konstante festlegen und ändern.

Jetzt habe ich eine Ansicht, wo ich verschiedene Subviews zur Laufzeit hinzufügen. Diese Subviews befinden sich in eigenen NIBs, was bedeutet, dass ich ihre Breite und Höhe nicht festlegen kann. Also dachte ich, ich würde die Einschränkungen hinzufügen, sobald die Ansicht zu einem Superview hinzugefügt wird. Dies wird in viewDidMoveToSuperview ausgeführt.

Die Einschränkungen werden hinzugefügt, ich kann dies mit einem NSLog bestätigen. Jetzt

"<NSLayoutConstraint:0x100605cc0 H:[ITControlPanelChildView:0x100616eb0(269)]>", 
"<NSLayoutConstraint:0x100614410 V:[ITControlPanelChildView:0x100616eb0(317)]>" 

schließlich, wenn ich versuche, den Zwang zu verändern [constraint setConstant:somethingDifferent]; mit erhalte ich die folgende Ausnahme:

Unable to simultaneously satisfy constraints: 
(
    "<NSLayoutConstraint:0x10192fcb0 V:[ITControlPanelChildView:0x10192e4f0(100)]>", 
    "<NSAutoresizingMaskLayoutConstraint:0x10053ff10 h=--& v=&-- V:[ITControlPanelChildView:0x10192e4f0(317)]>" 
) 

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x10192fcb0 V:[ITControlPanelChildView:0x10192e4f0(100)]> 

Das ist genau die Einschränkung ich zu ändern bin versucht. Kann mir jemand erklären, warum das passiert?


EDIT

Ich habe gerade gelesen, dass die NSAutoresizingMaskLayoutConstraint s automatisch hinzugefügt werden, die Sie, wenn Sie [self setTranslatesAutoresizingMaskIntoConstraints:NO]; gesetzt deaktivieren.

Wenn ich es deaktiviere, funktioniert es.

Noch besser wäre, wenn ich auf die NSAutoresizingMaskLayoutConstraint zugreifen könnte, die erstellt werden. Weiß jemand wie das funktioniert?

+0

Ich denke, du hast diese Änderung hinzugefügt, während ich meine Antwort geschrieben habe! Ist Autolayout in der Xib für die Unteransicht aktiviert? Können Sie den Code anzeigen, den Sie zum Hinzufügen der Unteransicht verwenden? – jrturton

+0

@jrturton Ja, das automatische Layout ist aktiviert. Vielleicht hast du mich falsch verstanden, es funktioniert. Ich dachte nur, es wäre nett, wenn ich die 'NSAutoresizingMaskLayoutConstraint' verwenden könnte, die bereits für mich erstellt wurden, anstatt sie zu deaktivieren und die Einschränkungen selbst hinzuzufügen. Hast du verstanden was ich meine? – NSAddict

+0

tue ich, aber du kannst nicht. Ich bin überrascht, dass sie auf einer Ansicht erscheinen, die auf der obersten Ebene in einem Autolayout-Xib definiert ist, weshalb ich nach dem Code gefragt habe. – jrturton

Antwort

8

Wie im Rest der Protokollnachricht angegeben, die Sie nicht enthalten haben, haben Sie Autoresizing-Einschränkungen, die Sie nicht wollen oder brauchen.

Sie können diese entfernen, wenn Sie die Unteransicht hinzufügen. In dem oben beschriebenen Verfahren Sie verwenden, fügen Sie einfach die folgende Zeile:

self.translatesAutoresizingMaskIntoConstraints = NO; 

Obwohl, wenn Sie die Ansicht in einem separaten Spitze schaffen, wo es seine Größe von zu bekommen? Gibt es nicht bereits Größenbeschränkungen, für die Sie einfach Outlets erstellen können?

1

Ich hatte dieses Problem zweimal.

Ich verwendete eine Technik beschrieben in Cocoa Programmierung für Mac OSX 4. Ed von Hillegass & Preble. Das Buch empfiehlt, eine NSBox als Ansichts-Container zu verwenden und die Ansichten mithilfe von Code in diese zu verschieben.Das Buch enthält auch einen praktischen Code zum manuellen Ändern der Größe des externen Fensters, in dem die Ansicht enthalten ist, zu der Sie gerade gewechselt haben.

Das erste Mal, dass ich ihre Technik habe ich versucht, diese Ausnahme bekam:

2013-01-05 22:56:05.103 MyApp[17717:303] Unable to simultaneously satisfy constraints: 
(
    "<NSAutoresizingMaskLayoutConstraint:0x100141330 h=--& v=--& H:[NSView:0x10012fdf0(4)]>", 
"<NSLayoutConstraint:0x1001316c0 H:[NSScrollView:0x100123ff0]-(NSSpace(20))-| (Names: '|':NSView:0x10012fdf0)>", 
"<NSLayoutConstraint:0x1001315d0 H:|-(NSSpace(20))-[NSScrollView:0x100123ff0] (Names: '|':NSView:0x10012fdf0)>") 

Will attempt to recover by breaking constraint 

Frustrierend genug musste ich die Benutzeroberfläche und in der neu erstellten Version Refactoring (die eher auf NSDocument basiert als eine einfache Fenster) Ich habe das gleiche Problem erneut angetroffen.

Wenn ich translateAutoResizingConstraints in den Unteransichten auf NEIN setze, werden sie nicht richtig angeordnet. Aber diese Unteransichten sind komplex, daher ist es keine Lösung, weil meine Fenster nicht angelegt sind. Das verhindert jedoch, dass die Ausnahme ausgelöst wird.

Wenn ich AutoLayout auf der obersten Ebene NSDocument-basierten XIB-Fenster deaktivieren - dann wird die Ausnahme auch nicht ausgelöst werden. Aber dann ist das Layout für die Top-Level-Elemente falsch und die Box ist nicht richtig dimensioniert. Das ist nicht so komplex, dass ich es nicht manuell auslegen könnte, denke ich.

Die seltsame Sache ist auf meiner ersten Version der Benutzeroberfläche funktioniert es ohne Wurf. In der ersten Version ist die Option "Automatisches Layout" für die Ansicht der obersten Ebene und alle Unteransichten festgelegt.

Ich kann nicht für das Leben von mir finden, welche obskure Einstellung in einem eingeschaltet wird, aber nicht das andere. Ich habe den exakt gleichen Code eingefügt, der in der Fensterversion funktioniert, um Ansichten in die dokumentbasierte Version zu tauschen, und ich ging durch Kontrolle, indem ich jede Einstellung überprüfte.

Meine Erinnerung an die Behebung des Problems das erste Mal ist, dass ich AutoLayout auf dem XIB ausgeschaltet hatte, aber wenn ich es nun versuche, zum zweiten Mal zu beheben, ist das AutoLayout eingeschaltet und es funktioniert gut.

Erste Version funktioniert - zweite nicht. Das einzige, was mir einfällt, ist, dass irgendwie etwas in NSDocument oder etwas anderem das Problem verursacht.

Allerdings habe ich eine Möglichkeit gefunden, es im zweiten Fall zu beheben: Deaktivieren Sie das Kontrollkästchen "AutoResizes Subviews" für die NSBox als Ansicht Container verwendet.

Warum dies nicht in der ersten Version der Benutzeroberfläche erforderlich ist (was mit diesem Kontrollkästchen funktioniert) ist ein Rätsel.

Wie auch immer - hier dokumentiert, falls es jemand anderem hilft.

Verwandte Themen