Wenn Sie das X der Unteransicht im Autolayout zentrieren, wird "nicht auf die Einschränkung vorbereitet" angezeigt.


82

Ich habe eine benutzerdefinierte UIView-Unterklasse, die über eine Schreibfeder initialisiert wird.

In -awakeFromNiberstelle ich eine Unteransicht und versuche, sie in der Übersicht zu zentrieren.

[self setInteralView: [[UIView alloc] init]];
[[self internalView] addConstraint: [NSLayoutConstraint constraintWithItem: [self internalView]
                                                                 attribute: NSLayoutAttributeCenterX
                                                                 relatedBy: NSLayoutRelationEqual
                                                                    toItem: self
                                                                 attribute: NSLayoutAttributeCenterX
                                                                multiplier: 1
                                                                  constant: 0]];

Dies bricht ab und verursacht die folgende Ausgabe:

2013-08-11 17:58:29.628 MyApp[32414:a0b] The view hierarchy is not prepared for the constraint: <NSLayoutConstraint:0xc1dcc80 UIView:0xc132a40.centerX == MyView:0xc1315a0.centerX>
    When added to a view, the constraint's items must be descendants of that view (or the view itself). This will crash if the constraint needs to be resolved before the view hierarchy is assembled. Break on -[UIView _viewHierarchyUnpreparedForConstraint:] to debug.
2013-08-11 17:58:29.630 MyApp[32414:a0b] View hierarchy unprepared for constraint.
    Constraint: <NSLayoutConstraint:0xc1dcc80 UIView:0xc132a40.centerX == MyView:0xc1315a0.centerX>
    Container hierarchy: 
<UIView: 0xc132a40; frame = (0 0; 0 0); clipsToBounds = YES; layer = <CALayer: 0xc132bc0>>
    View not found in container hierarchy: <MyView: 0xc1315a0; frame = (-128 -118; 576 804); layer = <CALayer: 0xc131710>>
    That view's superview: <UIView: 0xc131a70; frame = (0 0; 320 568); autoresize = W+H; layer = <CALayer: 0xc131b50>>

Antworten:


95

Wie der Fehler anzeigt, müssen Sie die Einschränkung einer Ansicht hinzufügen, sodass die an der Einschränkung beteiligten Ansichten die Ansicht sind, zu der Sie sie hinzufügen, oder eine Unteransicht dieser Ansicht. Im Fall Ihres obigen Codes sollten Sie diese Einschränkung hinzufügen self, anstatt [self internalView]. Der Grund, warum es nicht wie geschrieben funktioniert, ist, dass eine der Ansichten, die an der Einschränkung ( self) beteiligt sind, nicht in der Ansichtshierarchie enthalten ist, wenn Sie nur [self internalView]und unten berücksichtigen .

Weitere Informationen finden Sie im Diskussionsteil der Dokumentation zur addConstraint:Methode.

Hier ist Ihre Codezeile, die wie vorgeschlagen behoben wurde:

UIView* internalView = [[UIView alloc] initWithFrame:CGRectZero];
internalView.translatesAutoresizingMaskIntoConstraints = NO;
[self setInternalView:internalView];

[self addConstraint: [NSLayoutConstraint constraintWithItem: [self internalMapView]
                                         attribute: NSLayoutAttributeCenterX
                                         relatedBy: NSLayoutRelationEqual
                                         toItem: self
                                         attribute: NSLayoutAttributeCenterX
                                         multiplier: 1
                                         constant: 0]];

Das gibt mir einen Fehler zu behaupten Unable to simultaneously satisfy constraints. Probably at least one of the constraints in the following list is one you don't want.Und dann bricht es<NSLayoutConstraint:0x126ad4c0 UIView:0xadd2e20.centerX == MyView:0xadd19b0.centerX>
Patrick Perini

1
Höchstwahrscheinlich, weil Sie die Übersetzung der Maske zur automatischen Größenänderung in Einschränkungen nicht deaktiviert haben. Ich werde meinen obigen Code aktualisieren, um dies zu tun. Sie müssen wahrscheinlich auch Breiten- / Höhenbeschränkungen hinzufügen, damit es sichtbar ist, und ich würde empfehlen, eine Einschränkung für das mittlere Y oder eine Art obere / untere Einschränkung für sich selbst hinzuzufügen, um das Layout gut zu definieren.
Charles A.

Sie können also kein Layout haben wie : @"V:|[v]|"? wie würde sich das auf eine Übersicht beziehen?
Sam

1
@Sam Das ist eine gültige Einschränkung, aber sie zentriert die durch dargestellte Ansicht nicht. [v]Sie gibt Ihnen obere und untere Einschränkungen der Standardgröße zwischen [v]den oberen und unteren Kanten und der Übersicht. Sie müssten es auch zur Übersicht hinzufügen, glaube ich.
Charles A.

8
Eine einfache Daumenregel: Alle Einschränkungen, die sich auf die Größe einer Ansicht beziehen, sollten derselben Ansicht hinzugefügt werden, und alle Einschränkungen, die sich auf ihre Position beziehen, sollten ihrem übergeordneten Element hinzugefügt werden.
Deepak GM

117

Für andere, die hierher kommen: Ich habe diesen Fehler erhalten, weil ich die Einschränkungen hinzugefügt habe, bevor ich die Unteransichten zur Hierarchie hinzugefügt habe.


Danke, du hast mir viel Zeit gespart!
Stas

Dies ist der häufigste Grund für diesen Fehler, den ich bisher bemerkt habe.
Ayan Sengupta

genau und wenn Sie das tun, ist constraintWithItem: youViewder Gegenstand nicht darin vorhanden!
Nazir

36

Kurze Antwort : Eltern- und Kinderansicht tauschen .
Angenommen, selfdie übergeordnete Ansicht:

  • schlecht :[subview addConstraint [NSLayoutConstraint constraintWithItem:self...

  • gut :[self addConstraint [NSLayoutConstraint constraintWithItem:subview...


Schnell

subview.translatesAutoresizingMaskIntoConstraints = false
self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat(
    "H:|-0-[subview]-0-|",
    options: .DirectionLeadingToTrailing,
    metrics: nil,
    views: ["subview":subview]))

Obj-C

[subview setTranslatesAutoresizingMaskIntoConstraints:NO];
[self addConstraints:[NSLayoutConstraint
                      constraintsWithVisualFormat:@"H:|-0-[subview]-0-|"
                      options:NSLayoutFormatDirectionLeadingToTrailing
                      metrics:nil
                      views:NSDictionaryOfVariableBindings(subview)]];

10

Zusätzliche Tipps:

Ich habe eine neu entwickelte App, die unter iOS7 einwandfrei läuft, aber unter iOS8 die Fehlermeldung "Die Ansichtshierarchie ist nicht auf die Einschränkung vorbereitet" wird angezeigt.

In einem anderen Beitrag heißt es, dass die (Unter-) Ansichten hinzugefügt werden müssen, bevor Einschränkungen erstellt werden. Ich habe das getan, aber immer noch den Fehler bekommen.

Dann fand ich heraus, dass ich Einschränkungen unter - (void) viewDidAppear anstelle von viewDidLoad erstellen sollte


2
Beim viewDidAppear()Aufruf ist die Ansicht für den Benutzer bereits sichtbar. Wenn Sie Einschränkungen ändern, sollte dies vorher erfolgen viewWillLayoutSubviews(). Mehr über den Lebenszyklus hier: medium.com/@SergiGracia/…
maganap

6

Dies ist eine alte Frage, aber ich möchte diese Zeile aus den Dokumenten hervorheben:

Setzen Sie bei der Entwicklung für iOS 8.0 oder höher die isActive-Eigenschaft der Einschränkung auf true, anstatt die Methode addConstraint (_ :) direkt aufzurufen. Die Eigenschaft isActive fügt die Einschränkung automatisch hinzu und entfernt sie aus der richtigen Ansicht.

Zumindest wird dadurch ein Fehlerpunkt behoben, da Sie sich nicht mehr darum kümmern müssen, addConstraint in der falschen Ansicht aufzurufen


2

In meinem Fall wurde es gelöst, indem die Stammansicht als Container mit Einschränkungen anstelle einer aktuell erstellten Ansicht verwendet wurde.

Ich meine, verwenden Sie inside viewController

view.addConstraints([leftConstraintImage, topConstraintImage]) anstatt imageView.addConstraints...


1

Wie @CharlesA in seiner Antwort hervorhebt, besteht das Problem darin, dass sich die von Ihnen hinzugefügte Ansicht nicht in der richtigen Ansichtshierarchie befindet. Seine Antwort ist gut, aber ich werde einige Details für einen bestimmten Anwendungsfall erläutern, der dieses Problem für mich verursacht hat:

Dies geschah, als ich versuchte, einer Ansicht, deren Ansichtscontroller ich mit instanziiert hatte, Einschränkungen hinzuzufügen instantiateViewControllerWithIdentifier. Um das Problem zu lösen, habe ich verwendet [childViewController didMoveToParentViewController:self]. Dadurch wurde die Ansicht in die Ansichtshierarchie aufgenommen, auf die durch meine Einschränkung verwiesen wurde.


0

Fügen Sie zuerst Ihre Unteransicht und dann Ihre Einschränkungen wie folgt hinzu

addSubview(yourSubViewHere)
yourSubViewHere.translatesAutoresizingMaskIntoConstraints = false

addConstraint(NSLayoutConstraint(....
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.