Search code examples
iosautolayoutviewdidload

IOS/Autolayout: When in lifecycle to set constraints for elements created in code


Most of my scene is in storyboard and uses autolayout. But I want to create a UITableView, label and view in code and constrain them within the overall autlayout. My question is where in the lifecycle should I create the constraints.

Right now, I create hidden versions of the elements in ViewDidLoad and then customize and display them in View Will Appear based on data. I don't think I can put the layout constraints in ViewDidLoad, because the compiler won't know where all the views from storyboard are located. On the other hand, I don't want to recreate these constraints everytime viewWillAppear fires. Most don't change and at most I might want to update one or two.

Should I place the constraints in viewWillAppear and condition creating them on some test whether they were already created? Or should I put them somewhere else such as viewDidlayoutSubviews or viewDidAppear?

Thanks for any suggestions.

This is the code that creates the constraints:

  NSLayoutConstraint *contop = [NSLayoutConstraint constraintWithItem:_stepsTableView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:_stepNames attribute:NSLayoutAttributeBottom multiplier:1 constant:12];
     NSLayoutConstraint *contrail = [NSLayoutConstraint
     constraintWithItem:_stepsTableView attribute:NSLayoutAttributeTrailing
     relatedBy:NSLayoutRelationEqual toItem:self.scrollView
     attribute:NSLayoutAttributeTrailing multiplier:1 constant:20];
     NSLayoutConstraint *conlead = [NSLayoutConstraint
     constraintWithItem:_stepsTableView attribute:NSLayoutAttributeLeading
     relatedBy:NSLayoutRelationEqual toItem:self.scrollView
     attribute:NSLayoutAttributeLeading multiplier:1 constant:20];

     NSLayoutConstraint *conbot = [NSLayoutConstraint
     constraintWithItem:_stepsTableView attribute:NSLayoutAttributeBottom
     relatedBy:NSLayoutRelationEqual toItem:self.scrollView
     attribute:NSLayoutAttributeBottom multiplier:1 constant:20];
    NSLayoutConstraint *conheight = [NSLayoutConstraint constraintWithItem:_stepsTableView
                                                                        attribute:NSLayoutAttributeHeight
                                                                        relatedBy:NSLayoutRelationEqual
                                                                           toItem:nil
                                                                        attribute:NSLayoutAttributeNotAnAttribute
                                                                       multiplier:1.0
                                                                         constant:height];

      [self.scrollView removeConstraint: _bottomConstraint];

      [self.scrollView  addConstraints:@[contop,contrail,conlead,conbot,conheight]];

     [self.view layoutIfNeeded];

Solution

  • Any programmatically created constraints should be placed in viewDidLayoutSubviews and wraped with once bool value as the function is being called multiple times during launch of a viewController

       -(void)viewDidLayoutSubviews
       {
          if(once){
    
            once = NO;
    
    
          _stepsTableView.translatesAutoresizingMaskIntoConstraints = NO;
    
    
         NSLayoutConstraint *contop = [NSLayoutConstraint constraintWithItem:_stepsTableView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:_stepNames attribute:NSLayoutAttributeBottom multiplier:1 constant:12];
         NSLayoutConstraint *contrail = [NSLayoutConstraint
         constraintWithItem:_stepsTableView attribute:NSLayoutAttributeTrailing
         relatedBy:NSLayoutRelationEqual toItem:self.scrollView
         attribute:NSLayoutAttributeTrailing multiplier:1 constant:20];
         NSLayoutConstraint *conlead = [NSLayoutConstraint
         constraintWithItem:_stepsTableView attribute:NSLayoutAttributeLeading
         relatedBy:NSLayoutRelationEqual toItem:self.scrollView
         attribute:NSLayoutAttributeLeading multiplier:1 constant:20];
    
         NSLayoutConstraint *conbot = [NSLayoutConstraint
         constraintWithItem:_stepsTableView attribute:NSLayoutAttributeBottom
         relatedBy:NSLayoutRelationEqual toItem:self.scrollView
         attribute:NSLayoutAttributeBottom multiplier:1 constant:20];
        NSLayoutConstraint *conheight = [NSLayoutConstraint constraintWithItem:_stepsTableView
                                                                            attribute:NSLayoutAttributeHeight
                                                                            relatedBy:NSLayoutRelationEqual
                                                                               toItem:nil
                                                                            attribute:NSLayoutAttributeNotAnAttribute
                                                                           multiplier:1.0
                                                                             constant:height];
    
          [self.scrollView removeConstraint: _bottomConstraint];
    
          [self.scrollView  addConstraints:@[contop,contrail,conlead,conbot,conheight]];
    
         [self.view layoutIfNeeded];
    
    
          }
    
       }