Auto Layout causes infinite layoutSubviews loop
Asked Answered
S

3

5

I'm really puzzled by this, when I use auto layout on a subview the layoutSubview method loops infinitely.

All I'm doing is:

- (id)init
{
    self = [super init];
    if(self)
    {
        self.backgroundColor = [UIColor grayColor];
        _imageView = [[UIImageView alloc] init];
        _imageView.translatesAutoresizingMaskIntoConstraints = NO;
        [self addSubview:_imageView];

        [self applyConstraints];

    }
    return self;
}

-(void)applyConstraints
{
    [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[_imageView]-0-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_imageView)]];
    [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[_imageView]-0-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_imageView)]];
}

And this causes an infinite loop in layoutSubviews. Actually even when applyConstraints is not called the loop occurs, the only way to stop it from happening is setting 'translatesAutoresizingMaskIntoConstraints' to YES.

Has anyone encountered/solved this problem before?

Update Just to clarify, this is an UIView subclass, which is used within a view controller. The view itself does not use auto layout, instead it's frame is set the old fashioned way after initialization.

Simoniac answered 4/9, 2013 at 8:35 Comment(3)
Somewhere else you are doing wrong I guess, because I have copy pasted your code and commented translatesAutoresizingMaskIntoConstraints, still it is working fine, layoutSubview is not getting called infinitely.Plenitude
I've worked around it using frames for now, when I get around to it I'll try reproduce this in an empty project, I'll update the question when I do. Meanwhile, do you know what could cause the infinite loop? I can't really seem to find anything on the subject of an infinite layoutSubviews loop anywhere.Simoniac
You were right, it was caused somewhere else. One of the superviews removed & re-added the subviews within it's layoutSubviews method. I'm not sure why, as it's absolutely unnecessary...Simoniac
S
7

The loop was caused by one of the superviews, which was removing its subviews, setting their (possibly new) frame and then re-adding them. As the piece of code was absolutely unnecessary I removed it which fixed the problem.

Simoniac answered 4/9, 2013 at 14:1 Comment(2)
Good that you figured out the problem. :)Plenitude
Indeed, Changing frame is not a probleme, but creating new UIVIEW and adding them to viewcontrollers view make didLayoutSubviews being call again. And your right, this piece of code is unnecessary, no need to remove and recreate, juste reuse.Hyoscyamine
P
20

This might help you.

layoutSubviews will be called

  • When frame of the view changes
  • When a view removed from the superview then it will be called on superview
  • In UIScrollview, during scrolling.
  • While adding the view to superView.
  • During orientation change.
Plenitude answered 5/9, 2013 at 4:0 Comment(0)
S
7

The loop was caused by one of the superviews, which was removing its subviews, setting their (possibly new) frame and then re-adding them. As the piece of code was absolutely unnecessary I removed it which fixed the problem.

Simoniac answered 4/9, 2013 at 14:1 Comment(2)
Good that you figured out the problem. :)Plenitude
Indeed, Changing frame is not a probleme, but creating new UIVIEW and adding them to viewcontrollers view make didLayoutSubviews being call again. And your right, this piece of code is unnecessary, no need to remove and recreate, juste reuse.Hyoscyamine
N
1

This also turns up If there is an ambiguity, like two undetermined larger/less than equations. You are supposed to change one of these constraints to direct equality. Also Try to detect this ambiguity by tracing.

Nihil answered 26/8, 2015 at 14:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.