2

I don't know what I'm doing wrong: I'm creating a UIView that occupies all the screen (it has already constraints) and then, programmatically I'm creating an UI Image View:

_panel = [[UIImageView alloc] initWithImage:[self loadImageForKey:@"registerPanel"]];
_panel.frame = CGRectMake(0, 0, 100, 100);
_panel.exclusiveTouch = YES;
_panel.userInteractionEnabled = YES,
[self.scrollView addSubview:_panel];

And here it comes the problem: I'm adding constraints to the panel I created but it crashes (I'm doing it on the ViewWillAppear):

NSLayoutConstraint *centreHorizontallyConstraint = [NSLayoutConstraint
                                                    constraintWithItem:_panel
                                                    attribute:NSLayoutAttributeCenterX
                                                    relatedBy:NSLayoutRelationEqual
                                                    toItem:self.view
                                                    attribute:NSLayoutAttributeCenterX
                                                    multiplier:1.0
                                                    constant:0];

NSLayoutConstraint *centreVerticalConstraint = [NSLayoutConstraint
                                                constraintWithItem:_panel
                                                attribute:NSLayoutAttributeCenterX
                                                relatedBy:NSLayoutRelationEqual
                                                toItem:self.view
                                                attribute:NSLayoutAttributeCenterX
                                                multiplier:1.0
                                                constant:0];


[_panel addConstraint:centreHorizontallyConstraint];
[_panel addConstraint:centreVerticalConstraint];

Error message: 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.

6
  • 1
    " but it crashes" Any error message in console when it crashes then ? Which line exactly causes the crash? Commented Aug 23, 2018 at 15:50
  • Have you added your scrollView as a subview of self.view? Commented Aug 23, 2018 at 15:58
  • Yes, I did. [self.view addSubview:self.scrollView]; Commented Aug 23, 2018 at 16:00
  • 1
    Where is [_panel setTranslatesAutoresizingMaskIntoConstraints: NO]; Commented Aug 23, 2018 at 16:01
  • " When added to a view, the constraint's items must be descendants of that view (or the view itself)" Check before that _panel.superview == self.view, _panel.superview.superview == self.view` (according to your code), or _panel.superview....superview == self.view` which doesn't seems to be the case. Commented Aug 23, 2018 at 16:07

2 Answers 2

7

You can constrain a scrollView's subview to the scrollView's parent (self.view in this case), but that's probably not what you want.

Edit: For clarification, the reason you were getting the error was because you initialize your constraints:

toItem:self.view

and then you try to add them:

[_panel addConstraint:centreHorizontallyConstraint];
[_panel addConstraint:centreVerticalConstraint];

You want to add them to the toItem object:

[self.view addConstraint:centreHorizontallyConstraint];
[self.view addConstraint:centreVerticalConstraint];

Again, you probably don't want to center _panel in the main view, but this will compile and run:

#import "AddPanelScrollViewController.h"   /// just default .h

@interface AddPanelScrollViewController ()

@property (strong, nonatomic) UIScrollView *scrollView;
@property (strong, nonatomic) UIImageView *panel;

@end

@implementation AddPanelScrollViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    _scrollView = [UIScrollView new];
    _scrollView.translatesAutoresizingMaskIntoConstraints = NO;

    [self.view addSubview:_scrollView];

    [_scrollView.topAnchor constraintEqualToAnchor:self.view.topAnchor constant:20.0].active = YES;
    [_scrollView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor constant:-20.0].active = YES;
    [_scrollView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:20.0].active = YES;
    [_scrollView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor constant:-20.0].active = YES;

    _scrollView.backgroundColor = [UIColor blueColor];

    _panel = [UIImageView new];

    // required
    _panel.translatesAutoresizingMaskIntoConstraints = NO;

    [self.scrollView addSubview:_panel];

    // frame will be ignored when using auto-layout / constraints
//  _panel.frame = CGRectMake(0, 0, 100, 100);

    _panel.exclusiveTouch = YES;
    _panel.userInteractionEnabled = YES;
    _panel.backgroundColor = [UIColor redColor];

    // _panel needs width and height constraints
    [_panel.widthAnchor constraintEqualToConstant:100.0].active = YES;
    [_panel.heightAnchor constraintEqualToConstant:100.0].active = YES;

    NSLayoutConstraint *centreHorizontallyConstraint = [NSLayoutConstraint
                                                        constraintWithItem:_panel
                                                        attribute:NSLayoutAttributeCenterX
                                                        relatedBy:NSLayoutRelationEqual
                                                        toItem:self.view
                                                        attribute:NSLayoutAttributeCenterX
                                                        multiplier:1.0
                                                        constant:0];

    NSLayoutConstraint *centreVerticalConstraint = [NSLayoutConstraint
                                                    constraintWithItem:_panel
                                                    attribute:NSLayoutAttributeCenterY
                                                    relatedBy:NSLayoutRelationEqual
                                                    toItem:self.view
                                                    attribute:NSLayoutAttributeCenterY
                                                    multiplier:1.0
                                                    constant:0];

    // if constraints are releated to "self.view" that's where they need to be added
    [self.view addConstraint:centreHorizontallyConstraint];
    [self.view addConstraint:centreVerticalConstraint];

}
Sign up to request clarification or add additional context in comments.

Comments

2

First you can't create constraints between panel & self.view because there is no common parent , instead you want to create them with the scrollview

NSLayoutConstraint *centreHorizontallyConstraint = [NSLayoutConstraint
                                                    constraintWithItem:_panel
                                                    attribute:NSLayoutAttributeCenterX
                                                    relatedBy:NSLayoutRelationEqual
                                                    toItem:self.scrollView 
                                                    attribute:NSLayoutAttributeCenterX
                                                    multiplier:1.0
                                                    constant:0];

NSLayoutConstraint *centreVerticalConstraint = [NSLayoutConstraint
                                                constraintWithItem:_panel
                                                attribute:NSLayoutAttributeCenterY
                                                relatedBy:NSLayoutRelationEqual
                                                toItem:self.scrollView 
                                                attribute:NSLayoutAttributeCenterY
                                                multiplier:1.0
                                                constant:0];


[_scrollView  addConstraint:centreHorizontallyConstraint];
[_scrollView  addConstraint:centreVerticalConstraint];

Also both constraints are centerX , you need also width & height , or better top , leading , trailing and bottom to scrollView ,,, with width and height static or proportional to self.view

//

Also for any view you want to add constraints programmatically you must set

[self.scrollView setTranslatesAutoresizingMaskIntoConstraints: NO];
[self.panel setTranslatesAutoresizingMaskIntoConstraints: NO];

3 Comments

Crash again when I try to set the Constraint: 'Unable to install constraint on view. Does the constraint reference something from outside the subtree of the view? That's illegal. constraint:<NSLayoutConstraint:0x7ff484796aa0 UIImageView:0x7ff482f871d0.centerX == UIScrollView:0x7ff484798d60.centerX> view:<UIImageView: 0x7ff482f871d0; frame = (75 200; 887.5 345); opaque = NO; layer = <CALayer: 0x7ff4845a3290>>'
Do you add the constraint to the scrollView or panel ?? , it must be added to the scrollView
I could not enforce the constraints that I indicated through code, I tried all day and rereading this answer I solved! The documentation of the setTranslatesAutoresizingMaskIntoConstraints method It helped me understand what was wrong with the code! I solved by setting: [self.myChildView setTranslatesAutoresizingMaskIntoConstraints: NO ]; --- Thank you! ---

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.