iOS 8:为啥 NSLayoutAttributeCenterX 无法将我的视图居中? (适用于 iOS 7)

Posted

技术标签:

【中文标题】iOS 8:为啥 NSLayoutAttributeCenterX 无法将我的视图居中? (适用于 iOS 7)【英文标题】:iOS 8: Why is NSLayoutAttributeCenterX failing to center my views? (works in iOS 7)iOS 8:为什么 NSLayoutAttributeCenterX 无法将我的视图居中? (适用于 iOS 7) 【发布时间】:2014-12-04 03:12:04 【问题描述】:

我有一些在 ios 7 中可以使用的自动布局代码,但在 iOS 8 中没有。我的代码在两个版本之间没有变化。

情况是我有一个视图控制器,其中包含一些应该垂直堆叠的子视图,如下所示:

但是,当我在 iOS 8 上运行相同的代码时,会发生以下情况:

设置我的约束的代码如下:

- (void) updateViewConstraints 
    [super updateViewConstraints];

    NSDictionary *viewsDictionary = @
        @"timeLabel": self.timeLabel,
        @"recordingStateImage": self.recordingStateImage,
        @"recordButton": self.recordButton,
        @"spacer1": spacer1,
        @"spacer2": spacer2,
        @"superview": self.view
    ;

    if (!portraitConstraints) 
        //
        // Portrait Layout
        //

        portraitConstraints = [[NSMutableArray alloc] initWithArray:
            [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[timeLabel][spacer1][recordingStateImage][spacer2(==spacer1)][recordButton(100)]-|"
                                                    options:0
                                                    metrics:0
                                                      views:viewsDictionary]];

        [portraitConstraints addObjectsFromArray:@[
            [NSLayoutConstraint constraintWithItem:self.timeLabel
                                         attribute:NSLayoutAttributeCenterX
                                         relatedBy:NSLayoutRelationEqual
                                            toItem:self.view
                                         attribute:NSLayoutAttributeCenterX
                                        multiplier:1.f
                                          constant:0.f],
            [NSLayoutConstraint constraintWithItem:self.recordingStateImage
                                         attribute:NSLayoutAttributeCenterX
                                         relatedBy:NSLayoutRelationEqual
                                            toItem:self.view
                                         attribute:NSLayoutAttributeCenterX
                                        multiplier:1.f
                                          constant:0.f],
            [NSLayoutConstraint constraintWithItem:self.recordButton
                                         attribute:NSLayoutAttributeCenterX
                                         relatedBy:NSLayoutRelationEqual
                                            toItem:self.view
                                         attribute:NSLayoutAttributeCenterX
                                        multiplier:1.f
                                          constant:0.f]
        ]];
    

    [self.view removeConstraints:self.view.constraints];
    [self.view addConstraints:portraitConstraints];


我不确定为什么会这样。我已经检查了以下 SO 问题中提到的解决方法:

Autolayout problems with iOS8 with code that works fine on iOS7 Issue with Auto Layout on iOS 8 (code works perfectly on iOS 7)

但他们没有工作(这是在子视图而不是视图控制器的视图上调用 setNeedsLayout)。

如果有人在 iOS 8 上遇到了 NSLayoutAttributeCenterX 和自动布局的问题,我们将不胜感激。

【问题讨论】:

这里的容器视图是什么??? 什么时候调用updateViewConstraints?是否在生命周期方法中,例如 viewDidLoad 或 ViewWillAppear? 不要删除 updateViewConstraints 中的所有约束,它也会删除 XCode 添加的约束,并且你永远不会找回它 我还看到逻辑错误,如果 portraitCopnstaints 为 nill 怎么办?在这种情况下,您不应该删除任何常量。 【参考方案1】:

由于我的评论有助于解决问题,并且 OP 需要有关同一问题的更多信息,因此我发表评论作为答案


注意: 删除所有约束是不好的做法,因为它会删除 XCode 添加的所有约束以在设备中正确显示您的视图。

在横向和纵向模式下具有不同的 UI 如果您的视图在横向和纵向上有不同的约束(在紧凑和常规视图中)。 您可以使用尺寸等级 introduce in XCode6 和 backward comparability。 请按照这个blog 很好地解释尺寸等级。download project 在上面的博客中创建。输出: 以横向模式查看 以纵向模式查看:

【讨论】:

jw - 你对让这些东西向后兼容有什么想法吗?我最终做的是将我的旧逻辑保留在 updateConstraints 中,但仅在操作系统为 根据苹果大小分类向后兼容developer.apple.com/library/ios/recipes/… 我没有尝试但是这个问题我的帮助***.com/questions/24172860/…【参考方案2】:

事实证明,iOS 8 和 Xcode 6 为视图添加了额外的约束来帮助布局其元素。我通过上面的Jageen 和comment on a github issue 发现了这一点。

该问题的解决方案是不要在 iOS 8 中调用 [self.view removeConstraints],因为它会移除这些额外的必需约束。我个人对此的解决方法是利用 iOS 8 的 nib 及其特定方向的约束,并进行操作系统检查以仅在

如果有人对此问题有一个向后兼容的解决方法,可以在视图上调用removeConstraints,我会非常有兴趣看到它(因为我的纵向和横向布局不同)。

【讨论】:

因为你有不同的纵向和横向布局,你可以使用尺寸类(在 XCode6 中引入具有向后可比性),看看这个例子raywenderlich.com/83276/beginning-adaptive-layout-tutorial【参考方案3】:

我遇到了这个问题。在我的情况下,它的原因是这条线

self.view.translatesAutoresizingMaskIntoConstraints = NO; (自己是 UIViewController)

设置约束后,我在控制台的断点期间键入 po self.view.layer,它看起来很好。我在 viewDidLoad 中设置了约束(用 viewWillAppear 和 viewWillLayoutSubviews 进行实验会产生相同的结果)。但是,当我在 viewDidAppear 中添加断点并在控制台中键入相同的命令时,self.view 的宽度和高度都变为零。我删除了上面的行并且它起作用了。 self.view 保留了它的高度和宽度,并且子视图在中心对齐。

【讨论】:

以上是关于iOS 8:为啥 NSLayoutAttributeCenterX 无法将我的视图居中? (适用于 iOS 7)的主要内容,如果未能解决你的问题,请参考以下文章

ios 8为啥不能把提示上推

为啥 Safari Mobile 在 iOS 8 上处理许多输入字段时遇到问题

iOS 8:为啥 NSLayoutAttributeCenterX 无法将我的视图居中? (适用于 iOS 7)

为啥我的多通道混音器不再在 iOS 8 中播放?

iOS 10 / Xcode 8 设备上的 NSLog 似乎被截断了?为啥?

为啥 HTML5 视频不能在 IOS 8 WebApp(webview) 中播放?