Idrees
Idrees

Reputation: 133

NSLayoutConstraint is not being removed

I am trying to add a constraint programmatically to selected UITextField inside UITableViewCell. It is added successfully and selected text field width is being increased. But when I try to remove the added constraint then it doesn't work. Can Any one figure out where Am I doing the mistake?

-(void)setViewMovedUp:(BOOL)movedUp
{
    if (self.currentTextField.tag!=HEADER_FIELD_TAG) {
        [UIView beginAnimations:nil context:NULL];
        [UIView setAnimationDuration:0.3]; // if you want to slide up the view
        [self.view bringSubviewToFront:self.currentTextField];
        NSLayoutConstraint *constraintTrail = [NSLayoutConstraint constraintWithItem:self.currentTextField.superview
                                     attribute:NSLayoutAttributeTrailing
                                     relatedBy:NSLayoutRelationEqual
                                        toItem:self.currentTextField
                                     attribute:NSLayoutAttributeTrailing
                                    multiplier:1.0
                                      constant:0.0];

        CGRect rect = self.view.frame;
        CGRect tableRect = self.currentTextField.frame;
        if (movedUp)
        {
            // 1. move the view's origin up so that the text field that will be hidden come above the keyboard
            // 2. increase the size of the view so that the area behind the keyboard is covered up.
            [self.currentTextField.superview addConstraint:constraintTrail];
            rect.origin.y -= kOFFSET_FOR_KEYBOARD;
            rect.size.height += kOFFSET_FOR_KEYBOARD;
            tableRect.size.width += 800;

        }
        else
        {
            // revert back to the normal state.
            [self.currentTextField.superview removeConstraints:@[constraintTrail]];
            rect.origin.y += kOFFSET_FOR_KEYBOARD;
            rect.size.height -= kOFFSET_FOR_KEYBOARD;
            tableRect.size.width -= 800;
        }
        infoFieldTable.frame = tableRect;
        self.view.frame = rect;

        [UIView commitAnimations];
    }

}

Upvotes: 0

Views: 493

Answers (2)

Catalina T.
Catalina T.

Reputation: 3494

My suggestion would be to add the constraint only once (maybe in the setup method or event the storyboard and have an IBOutlet to it) and then active/deactivate it according to your logic.

-(void)setViewMovedUp:(BOOL)movedUp
{
    if (self.currentTextField.tag!=HEADER_FIELD_TAG) {

        // All your logic here ...

        // Set the active property on the constraint
        [self.constraintTrail setActive:movedUp];
    }
}

Another point would be that you are not calling layoutIfNeededafter you change the constraints. This method causes the view to relayout it's subviews with the new constraints.

Hope it works! Let me know how it goes though :)

Upvotes: 0

Lord Zsolt
Lord Zsolt

Reputation: 6557

Well it's obviously not working.

If I imagine right, setViewMovedUp is a setter, executed when the viewMovedUp property changes.

When the method is executed, you create a new constraint with:

    NSLayoutConstraint *constraintTrail = [NSLayoutConstraint constraintWithItem:self.currentTextField.superview
                                 attribute:NSLayoutAttributeTrailing
                                 relatedBy:NSLayoutRelationEqual
                                    toItem:self.currentTextField
                                 attribute:NSLayoutAttributeTrailing
                                multiplier:1.0
                                  constant:0.0];

Based on the value of movedUp you either add it or try to remove it. So if you set viewMovedUp to YES 5 times in a row, you'll have 5 constraints. When you set it to NO, you're trying to remove a newly created constraint, not the one which was previously added.


What you most likely want is to create a property for that constraint:

@property (nonatonic, strong) NSLayoutContraint *constraintTrail;

and change your code to:

    if (!self.contraintTrail) {
        self.contraintTail = [NSLayoutConstraint constraintWithItem:self.currentTextField.superview
                                                          attribute:NSLayoutAttributeTrailing
                                                          relatedBy:NSLayoutRelationEqual
                                                             toItem:self.currentTextField
                                                          attribute:NSLayoutAttributeTrailing
                                                         multiplier:1.0
                                                           constant:0.0];
    }

This way, you only create on NSLayoutContraint instance, and reuse it.

Upvotes: 1

Related Questions