Het centreren van de X van de subview in de autolayout geeft “niet voorbereid op de beperking”

Ik heb een aangepaste UIView-subklasse die wordt geïnitialiseerd via een punt.

In -awakeFromNibmaak ik een subview en probeer ik deze in zijn superview te centreren.

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

Dit verbreekt en veroorzaakt de volgende uitvoer:

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

Antwoord 1, autoriteit 100%

Voor anderen die hier komen: ik kreeg deze foutmelding, omdat ik de beperkingen heb toegevoegd voordat ik de subweergaven aan de hiërarchie toevoegde.


Antwoord 2, autoriteit 81%

Zoals de fout aangeeft, moet u de beperking zo aan een weergave toevoegen dat de weergaven die bij de beperking betrokken zijn, de weergave zijn waaraan u deze toevoegt of een subweergave van die weergave. In het geval van je bovenstaande code, zou je die beperking moeten toevoegen aan self, in plaats van aan [self internalView]. De reden dat het niet werkt zoals het is geschreven, is dat een van de weergaven die betrokken zijn bij de beperking (self) niet in de weergavehiërarchie staat als je alleen [self internalView]beschouwt en hieronder).

Zie voor meer informatie de discussiegedeelte van de documentatieover de addConstraint:-methode.

Hier is je coderegel, aangepast zoals ik voorstel:

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]];

Antwoord 3, autoriteit 31%

Kort antwoord: verwisselouder- en kindweergave.
Ervan uitgaande dat selfde bovenliggende weergave is:

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

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


Snel

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)]];

Antwoord 4, autoriteit 9%

Aanvullende tips:

Ik heb een nieuw ontwikkelde app die prima werkt op iOS7, maar krijg een foutmelding op iOS8 “De weergavehiërarchie is niet voorbereid op de beperking”.

Lees een ander bericht waarin staat dat de (sub)weergaven moeten worden toegevoegd voordat er beperkingen worden gemaakt. Ik heb dat gedaan, maar kreeg nog steeds de fout.

Toen kwam ik erachter dat ik beperkingen moest creëren onder -(void)viewDidAppear in plaats van viewDidLoad


Antwoord 5, autoriteit 5%

Dit is een oude vraag, maar ik wil je op deze regel uit de documenten wijzen:

Als u voor iOS 8.0 of hoger ontwikkelt, stelt u de eigenschap isActive van de beperking in op true in plaats van de methode addConstraint(_:) rechtstreeks aan te roepen. De eigenschap isActive voegt automatisch de beperking toe aan en verwijdert deze uit de juiste weergave.

Dit zal op zijn minst één storingspunt wegnemen, aangezien u zich geen zorgen meer hoeft te maken over het aanroepen van addConstraint in de verkeerde weergave


Antwoord 6, autoriteit 2%

In mijn geval werd het opgelost door de root-weergave te gebruiken als een container met beperkingen in plaats van een momenteel gemaakte weergave.

Ik bedoel, gebruik inside viewController

view.addConstraints([leftConstraintImage, topConstraintImage])
in plaats van imageView.addConstraints...


Antwoord 7

Zoals @CharlesA in zijn antwoord aangeeft, is het probleem dat de weergave die u toevoegt niet in de juiste weergavehiërarchie staat. Zijn antwoord is goed, maar ik ga wat details geven voor een bepaalde use-case die dit probleem voor mij veroorzaakte:

Dit gebeurde bij mij toen ik probeerde beperkingen toe te voegen aan een view waarvan ik de viewcontroller had geïnstantieerd met behulp van instantiateViewControllerWithIdentifier. Om het probleem op te lossen, gebruikte ik [childViewController didMoveToParentViewController:self]. Dit voegde de weergave toe aan de weergavehiërarchie waarnaar werd verwezen door mijn beperking.


Antwoord 8

Voeg eerst uw subView toe en voeg vervolgens uw beperkingen op deze manier toe

addSubview(yourSubViewHere)
yourSubViewHere.translatesAutoresizingMaskIntoConstraints = false
addConstraint(NSLayoutConstraint(....

Other episodes