Search code examples
iosobjective-cautolayoutnslayoutconstraintlayoutsubviews

iOS: Adding new constraints in a custom view the rely on the view's frame


I'm trying to understand when to override layoutSubviews versus updateConstraints.

I have created a custom view, and that view contains other views. I can't set the constraints for the view's subviews in the custom initializer I have as I don't know the custom view's frame yet.

Currently I have this:

-(void)layoutSubviews
{
    [super layoutSubviews];
    // Add new constraints
}

Then whenever I add or remove any of the subviews, I call [self setNeedsLayout];

Is this the correct way to do this? I am currently recreating the constraints whenever layoutSubviews is called. I've heard that updateConstraints might be what I want? But I'm not sure as the number of subviews does not remain constant, and thus, the number of constraints will not be constant either.


Solution

  • You should add constraint when you add the subviews. You may do this for each subview individually, or in a custom method if that can be generalized.

    The methods layoutSubvews and updateConstraints are callbacks, and they are called at specific points in the layout cycle. Especially, they are called multiple times, and that automatically prohibits you from using constraints, because there is a danger of creating constraints more than once.

    As the documentation stated, layoutSubviews should only be used when

    if the autoresizing and constraint-based behaviors of the subviews do not offer the behavior you want.

    If layoutSubviews is called, the current automatic layout is done, and adding, removing or modifying constraints might re-trigger the layout process. This might slow-down your app extremely.

    The documentation for updateConstraints includes also a clear statement when you should overwrite it:

    Override this method to optimize changes to your constraints.

    Changes to constraints doesn't mean adding constraints. If you need different constraints for your views for different times, you may deactivate unused and activate needed constraints at runtime. This could be done in updateConstraints.

    BTW: The (explicit) call of setNeedsLayout is usually unnecessary, especially if you have changed the view hierarchy or the layout constraints.