Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I'm trying to figure out autolayout recently. Almost I thought that I understand it with editor but when it comes to manage them with programmatically it's really hard.

Anyway let me explain the problem which i try to solve;

I have a tableviewcell with autolayout. In this cell I have a subview which i want to fill it later with code. So far it's fine. I also a custom view controller designed with autolayout. What I want to accomplish is repeating n times these different instance of view controllers view inside of subview with margin of lets say 10px to previous item.

Here is the hierarchy of the views;

--cell
----label1
----label2
----subview
------view controller's view 1
------view controller's view 2 
------view controller's view 3
..
..
------view controller's view n
----button
----button

Here is the code I came with so far;

self refers to tableviewcell self.workoutView refers to subview SPPostWorkoutItemViewController refers to inner controllers.

SPPostWorkoutItemViewController *previousController = nil;

    for(int i=0; i < p.workout.workoutItems.count; i++ ){

        WorkoutItem *workoutItem = p.workout.workoutItems[i];
        SPPostWorkoutItemViewController *workoutItemController = [[SPPostWorkoutItemViewController alloc]initWithWorkoutItem:workoutItem];

        if(previousController == nil){

            NSLayoutConstraint * cons = [NSLayoutConstraint constraintWithItem:workoutItemController.view
                                                                 attribute:NSLayoutAttributeTop
                                                                 relatedBy:NSLayoutRelationEqual
                                                                    toItem:self.workoutView
                                                                 attribute:NSLayoutAttributeTop
                                                                multiplier:1.0
                                                                  constant:10];

            [self.workoutView addConstraint:cons];
        }
        else{

            NSLayoutConstraint * cons = [NSLayoutConstraint constraintWithItem:workoutItemController.view
                                                                     attribute:NSLayoutAttributeTop
                                                                     relatedBy:NSLayoutRelationEqual
                                                                        toItem:previousController.view
                                                                     attribute:NSLayoutAttributeTop
                                                                    multiplier:1.0
                                                                      constant:10];

            [self.workoutView addConstraint:cons];
        }


        [self.workoutView addSubview:workoutItemController.view];
        previousController = workoutItemController;


    }
share|improve this question
add comment

1 Answer

up vote 0 down vote accepted

Here is the final solutiton I came with it. It's working perfect. I used Masonry layout framework. It really simplify the autolayout syntax and make it more readable.

There're todos to make autolayout work correctly.

  • container view does not have height constraint
  • top subview has constraint with container view from top
  • each subview has top constraint with previous subview
  • last subview has constraint with container view from bottom

Also to expand subview correctly I need to define label constraints in subview. I followed this answer, It explains perfectly.

Finally the code is, hope it helps others;

SPPostWorkoutItemViewController *previousController = nil;

for(int i=0; i < p.workout.workoutItems.count; i++ ){

    WorkoutItem *workoutItem = p.workout.workoutItems[i];
    SPPostWorkoutItemViewController *workoutItemController = [[SPPostWorkoutItemViewController alloc]initWithWorkoutItem:workoutItem];


    [self.workoutView addSubview:workoutItemController.view];

    //first workout item so margin with parent
    //also margin 6 pixel to parent from left side
    if(previousController == nil){

        [workoutItemController.view mas_makeConstraints: ^(MASConstraintMaker *make) {

            make.top.equalTo(self.workoutView.mas_top).with.offset(0);
            make.left.equalTo(self.workoutView.mas_left).with.offset(6);
        }];
    }
    else{

        //second workout item margin with previous one
        [workoutItemController.view mas_makeConstraints: ^(MASConstraintMaker *make) {

            make.top.equalTo(previousController.view.mas_bottom).with.offset(5);
            make.left.equalTo(self.workoutView.mas_left).with.offset(6);
        }];
    }

    //don't forget to margin last workout item with parent's bottom
    if(i == (p.workout.workoutItems.count - 1)){

        [workoutItemController.view mas_makeConstraints: ^(MASConstraintMaker *make) {

            make.bottom.equalTo(self.workoutView.mas_bottom).with.offset(0);
        }];
    }

    previousController = workoutItemController;        
}
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.