1

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;


    }
Fatih Donmez
  • 4,319
  • 3
  • 33
  • 45

1 Answers1

0

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;        
}
Community
  • 1
  • 1
Fatih Donmez
  • 4,319
  • 3
  • 33
  • 45