何时在 iOS 7 中使用 AutoLayout 更新约束

Posted

技术标签:

【中文标题】何时在 iOS 7 中使用 AutoLayout 更新约束【英文标题】:When to update constraints with AutoLayout in iOS 7 【发布时间】:2013-10-11 12:23:17 【问题描述】:

在我的应用程序中,我想调整 UITextView (self.message)、导航控制器视图的大小,并且我想在键盘显示时更改 UIScrollView (self.selectedMedia) 的位置。为了实现这一点,我使用了这个委托方法:

- (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];

当我运行这段代码时,我得到一个约束不能满足的错误:

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)]>

我想知道为什么 UITextView 的高度仍然是 380。语句[self.navigationController updateConstraints] 不是根据给定的约束调整高度吗?提交动画后是否应该更新约束?或者还有什么我忽略的?

【问题讨论】:

【参考方案1】:

使用自动布局时,您不应该设置视图的框架。相反,您应该调整约束,通常是“常量”属性。

在您的情况下,您正在更改视图的高度并在此过程中打破约束。

【讨论】:

你说得对,我删除了setFrameself.message。从情节提要中,我创建了一个附加到 UITextView (messageHeightConstraint) 高度约束的属性。之后我添加了一条语句来更新约束常量:self.messageHeightConstraint.constant = self.messageHeightConstraint.constant - keyboardHeight; 干得好!谢谢!【参考方案2】:

请注意我是否完全理解您的问题,但滚动视图在自动布局方面非常特别(请参阅技术说明 https://developer.apple.com/library/ios/technotes/tn2154/)

【讨论】:

以上是关于何时在 iOS 7 中使用 AutoLayout 更新约束的主要内容,如果未能解决你的问题,请参考以下文章

iOS 7 缩放不能在具有 AutoLayout 的 ScrollView 中工作,但在 iOS8/9 中工作

iOS:在tableView中通过Masonry使用autolayout在iOS7系统出现约束崩溃

以编程方式创建 AutoLayout 约束 (IOS) Xcode 7.0.1

我们如何在 iOS 7 上检测何时控制中心?

在iOS中使用autolayout调整内容大小的UILabel

在AutoLayout - iOS中,约束计数总是变为零