0
votes

I am trying to add a button to a UIstackview, programmatically. All this is in fitxero XIB.   The button is created correctly, but when adding the constraints I get the following error:

2020-05-21 17:51:08.328369+0200 eWAS[3391:567586] *** Terminating app due to uncaught exception 'NSGenericException', reason: 'Unable to install constraint on view. Does the constraint reference something from outside the subtree of the view?
That's illegal. constraint: < NSLayoutConstraint:0x282362b70 V:|-(0)-[UIButton:0x11c225a60'button'] (active, names: '|':UIStackView:0x11bfc13f0 ) > view:< UIButton: 0x11c225a60; frame = (0 0; 30 150); opaque = NO; layer = < CALayer: 0x2802e4220 > >'

   -(void) configureTabsWithTexts: (NSArray *) tabs{
    NSInteger tag = 0;

    UIButton *currentButton = [UIButton buttonWithType:UIButtonTypeSystem];
    [currentButton setTitle:@"Button1" forState:UIControlStateNormal];
    [currentButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
    [currentButton setTag:tag];
    [currentButton.titleLabel setFont:[UIFont systemFontOfSize:20]];
    [currentButton.titleLabel setTextColor:[UIColor whiteColor]];
    [currentButton setFrame:CGRectMake(0, 0, 30, 150)];
    currentButton.backgroundColor = [UIColor blackColor];

    [self.stackViewForButtons addSubview:currentButton];
    [currentButton setTranslatesAutoresizingMaskIntoConstraints:NO];

    NSMutableArray <NSLayoutConstraint *> *arrayConstraints = [[NSMutableArray alloc] init];

    currentButton.translatesAutoresizingMaskIntoConstraints = false;



    [currentButton addSubview:self.stackViewForButtons];

            [currentButton addConstraint: [NSLayoutConstraint constraintWithItem:currentButton
                                                           attribute:NSLayoutAttributeTop
                                                           relatedBy:NSLayoutRelationEqual
                                                           toItem:self.stackViewForButtons
                                                           attribute:NSLayoutAttributeTop
                                                          multiplier:1
                                                            constant:0]];
    [currentButton addConstraint: [NSLayoutConstraint constraintWithItem:currentButton
                                                           attribute:NSLayoutAttributeBottom
                                                           relatedBy:NSLayoutRelationEqual
                                                           toItem:currentButton.superview
                                                           attribute:NSLayoutAttributeBottom
                                                          multiplier:1
                                                            constant:0]];
    [currentButton addConstraint: [NSLayoutConstraint constraintWithItem:currentButton
                                                           attribute:NSLayoutAttributeWidth
                                                           relatedBy:NSLayoutRelationEqual
                                                           toItem:nil
                                                           attribute:NSLayoutAttributeNotAnAttribute
                                                          multiplier:1
                                                            constant:50]];

        [currentButton addConstraint: [NSLayoutConstraint constraintWithItem:currentButton
                                                               attribute:NSLayoutAttributeLeading
                                                               relatedBy:NSLayoutRelationEqual
                                                               toItem:currentButton.superview
                                                               attribute:NSLayoutAttributeLeading
                                                              multiplier:1
                                                                constant:0]];

}
1

1 Answers

0
votes

You have this line:

[self.stackViewForButtons addSubview:currentButton];

which seems fine, but then later you are doing:

[currentButton addSubview:self.stackViewForButtons];

which seems backwards and is probably the source of your problem. Try removing that latter line and see if it works. I doubt you want a UIButton to have a stack view as a subview. With both lines in place, there is a circular reference, which UIView probably figures out and removes the original superview of the UIButton, meaning that is nil when you are creating the later constraints (or maybe it removes the superview/subview relationship altogether).

As an aside, if you are using an actual UIStackView which it looks like you are, you shouldn't need any of these constraints done by hand. The entire point of UIStackView is to generate all those constraints for you. In that case, simply call:

    [self.stackViewForButtons addArrangedSubview:currentButton];
    [currentButton setTranslatesAutoresizingMaskIntoConstraints:NO];

and you should be done, provided you have configured the stack view correctly. Maybe you need the width constraint on each one, not sure. While you can add non-arranged subviews to a UIStackView, that should be rare. And even if that is intended in this case, you may be better off adding another UIStackView as a subview, then adding the buttons to that.