Martin de Keijzer
Martin de Keijzer

Reputation: 382

When to update constraints with AutoLayout in iOS 7

In my application I want to resize a UITextView (self.message), Navigation Controller's view and I want to change the position of a UIScrollView (self.selectedMedia) when the keyboard shows. To accomplish that I'm using this delegate method:

- (void)keyboardWillShow:(NSNotification *)notification
{
NSDictionary* userInfo = [notification userInfo];

NSTimeInterval animationDuration;
UIViewAnimationCurve animationCurve;
CGRect keyboardFrame;
CGRect navigationControllerFrame = self.navigationController.view.frame;
CGRect textViewFrame = self.message.frame;
CGFloat keyboardHeight;

[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&animationCurve];
[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&animationDuration];
[[userInfo objectForKey:UIKeyboardFrameBeginUserInfoKey] getValue:&keyboardFrame];

keyboardHeight = keyboardFrame.size.height;

[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:animationDuration];
[UIView setAnimationCurve:animationCurve];

[self.navigationController.view setFrame:CGRectMake(
                                                    navigationControllerFrame.origin.x,
                                                    navigationControllerFrame.origin.y,
                                                    navigationControllerFrame.size.width,
                                                    navigationControllerFrame.size.height - keyboardHeight
                                                    )];
[self.message setFrame:CGRectMake(
                                  textViewFrame.origin.x,
                                  textViewFrame.origin.y,
                                  textViewFrame.size.width,
                                  textViewFrame.size.height - keyboardHeight)];

if (self.selectedMedia.hidden == NO) {
    [self.selectedMedia setFrame:CGRectMake(
                                            self.selectedMedia.frame.origin.x,
                                            self.selectedMedia.frame.origin.y - keyboardHeight,
                                            self.selectedMedia.frame.size.width,
                                            self.selectedMedia.frame.size.height
                                            )];
}

[self.navigationController.view updateConstraints];
[UIView commitAnimations];
}

When I run this code, I get an error that the constraints cannot be satisfied:

2013-10-11 14:03:52.532 PoC[78199:a0b] Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
"<NSLayoutConstraint:0xe5502d0 V:[UITextView:0xf26da00(380)]>",
"<NSLayoutConstraint:0x8b93620 V:|-(0)-[UITextView:0xf26da00]   (Names: '|':UIView:0x8b978f0 )>",
"<NSLayoutConstraint:0x8b984c0 V:[UIScrollView:0x8b8f570]-(0)-|   (Names: '|':UIView:0x8b978f0 )>",
"<NSLayoutConstraint:0x8b98520 V:[UITextView:0xf26da00]-(0)-[UIScrollView:0x8b8f570]>",
"<NSAutoresizingMaskLayoutConstraint:0x8b9acf0 h=--& v=--& V:[UIView:0x8b978f0(244)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0xe5502d0 V:[UITextView:0xf26da00(380)]>

I wonder why the UITextView still has a height of 380. Doesn't the statement [self.navigationController updateConstraints] adjust the height based on the given constraints? Should the constraints be updated after committing the animation? Or is there something else I'm overlooking?

Upvotes: 2

Views: 10428

Answers (2)

Nikola Lajic
Nikola Lajic

Reputation: 4075

When using Autolayout you shouldn't be setting the view's frame. Instead you should adjust the constraints, usually the 'constant' property.

In your case, you are changing the height of a view and in the process breaking a constraint.

Upvotes: 6

Laurent Cerveau
Laurent Cerveau

Reputation: 152

Note sure if I understood exactly your problem, but the scroll view is pretty special in regards to autolayout (see technote https://developer.apple.com/library/ios/technotes/tn2154/)

Upvotes: 1

Related Questions