简体   繁体   中英

Constraints programmatically with Objective C

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.

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

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

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM