在iOS 8中发生的自动布局有一个恼人的问题,而在iOS 7中同样的设置也很好。
我简化并隔离了有问题的情况,下面是它应该如何工作-以及它在iOS 7中是如何工作的:

该特性由一个容器视图(蓝色)和三个子视图组成:
我添加了一个滑块,它通过修改容器的宽度约束来控制容器视图的宽度。
自动布局约束将标签锚定在左侧,按钮固定在右侧,图像视图被锚定在两侧,而没有宽度约束。
在iOS 8中,相同的设置如下所示:

请注意图像视图(黑线)是如何与容器视图右侧的偏移量锚定的。
我已经尝试了所有的方法,我不明白为什么在iOS 8中这种情况会有所不同,我已经多次删除和替换了所有的约束,但是仍然得到了相同的结果。
这些是分别设置在每个子视图上的约束:

这些是容器视图的约束:

容器视图的宽度约束由滑块操作,如下所示:

- (IBAction)handleSliderChange:(id)sender
{
self.buttonWidth.constant = self.slider.value * 1024.0;
[self.containerView setNeedsLayout];
[self.containerView setNeedsUpdateConstraints];
[self.containerView layoutIfNeeded];
[self.view setNeedsLayout];
[self.view setNeedsUpdateConstraints];
[self.view layoutIfNeeded];
}在iOS 8中有自动布局问题的其他人似乎能够通过直接在包含视图上调用setNeedsLayout和/或setNeedsUpdateConstraints来解决类似的问题,这就是为什么我在包含视图和根视图上调用它时非常明确的原因。我试过以上所有的组合,但似乎没有什么不同。
我开始失去寻找解决方案的希望,但也许这里的人已经处理过类似的情况,并能让这个问题变得更清晰?
编辑:,我应该补充说,我也尝试过设置从图像视图到标签和按钮的约束,而不是设置包含视图的边缘,结果是相同的。
编辑2:,这是我在试图隔离问题时使用的测试项目:下载
发布于 2014-10-10 12:23:22
这不是自动布局的问题,但必须是iOS 8中关于处理切片图像资产的一个bug。
使用您的示例项目:
UIImage *img = [UIImage imageNamed:@"pointer-dark-left"];
NSLog(@"alignmentRect: %@", NSStringFromUIEdgeInsets(img.alignmentRectInsets));
NSLog(@"capInsets: %@", NSStringFromUIEdgeInsets(img.capInsets));这段代码打印
// iOS 7
alignmentRect: {0, 0, 0, 0}
capInsets: {0, 5.5, 0, 134}
// iOS 8
alignmentRect: {0, 0, 0, 65.5}
capInsets: {0, 5.5, 0, 134}alignmentRectInsets.right是65.5!
作为记录在案,Autolayout使用对齐矩形,而UIImageView使用它的图像alignmentRectInsets。因此,您的self.line具有额外的右宽度的65.5pt。
当然,您没有在xcassets编辑器中设置对齐内嵌,我相信它是bug。

这里有一个丑陋的,但正在工作的解决办法:
- (void)viewDidLoad {
[super viewDidLoad];
self.line.image = [self.line.image imageWithAlignmentRectInsets:UIEdgeInsetsZero];
}发布于 2014-10-09 21:28:32
我觉得你把限制因素联系错了。
我构建了一个具有相同组件的应用程序,它运行得很好。也许您可以清除所有约束并重新设置。
我添加代码以编程方式完成它。
#import "ViewController.h"
@interface ViewController () {
NSLayoutConstraint* csViewWidth;
}
@end
@implementation ViewController
- (void)viewDidLoad {
NSDictionary *views = @{
@"label": self.uiLabel,
@"image": self.uiImage,
@"button": self.uiButton
};
NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[label]-[image]-[button]-|"
options:0
metrics:nil
views:views];
[self.view addConstraints:constraints];
NSArray *panelConstraint = [NSLayoutConstraint constraintsWithVisualFormat:@"H:[panel(320)]" options:0 metrics:nil views:@{ @"panel": self.uiPanel }];
csViewWidth = [panelConstraint firstObject];
[self.view addConstraints:@[csViewWidth]];
}
- (IBAction)onSliderChanged:(UISlider*)sender {
float containerWidth = self.view.frame.size.width;
csViewWidth.constant = sender.value * containerWidth;
}
@end该解决方案经过测试,工作良好。没有必要调用setNeedsLayout和layoutIfNeeded。
发布于 2014-10-10 15:00:26
那不是因为iOS的错误
图像被切错了
我用您的项目进行了测试,它现在按预期的方式工作。
切片必须是这样的:
在你的切片,你告诉ios采取长尾巴,这是打破了你的布局。
https://stackoverflow.com/questions/26287942
复制相似问题