【问题标题】:What is a 'UIView-Encapsulated-Layout-Width' constraint?什么是“UIView-Encapsulated-Layout-Width”约束?
【发布时间】:2014-02-05 08:36:49
【问题描述】:

我不断收到“无法同时满足约束”异常(Xcode 5、iOS 7、设备和模拟器),其中列表中的约束之一是这样的:

"<NSLayoutConstraint:0x165b23d0 'UIView-Encapsulated-Layout-Width'
H:[StoryPlayerCell:0x165affc0(0)]>"

我自己没有设置这个约束。它也不是NSAutoresizingMaskLayoutConstraint。 但它来自哪里?我怎样才能摆脱它?

我不知道。 而且我在 Apple 的文档中找不到任何关于 'UIView-Encapsulated-Layout-Width' 的信息。 甚至 Google 搜索也没有返回任何内容。

有什么建议吗?

PS:我在 UICollectionView 中使用此单元格,自定义子类为 UICollectionViewFlowLayout。也许'Encapsulated-Layout' 部分与此有关?

【问题讨论】:

  • 你能上传一个复制的示例项目吗?
  • 试试CSStickyHeaderFlowLayout 的示例。如果您正常滚动,则不会发生任何事情,但如果您滚动非常慢,则会引发错误。这有点随机且难以复制。
  • @andreamazz 我使用了示例,我认为这些代码导致了 Autolayout 异常。 CGFloat height = MAX(0, -y + maxY); CSStickyHeaderFlowLayout.m 中的第 79 行。如果您对高度使用静态值,例如 200,则不会再发生异常。我无法理解 UIView-Encapsulated-Layout 到底是什么,但似乎动态更改 UICollectionViewLayoutAttributes 框架可能会导致该问题。在示例项目中,它是高度,在 PO 的问题中,我猜是宽度。如果您认为这会有所帮助,也许我可以深入研究一下。
  • 使用静态值也会破坏视差效果。虽然使用CGFloat height = MAX(1, -y + maxY);,用 1 代替 0 可以解决问题,保持正确的视差效果。非常感谢您的帮助,一切顺利。
  • @andreamazz 你认为我可以用它作为答案吗,因为没有人回答?

标签: ios uicollectionview autolayout nslayoutconstraint uicollectionviewlayout


【解决方案1】:

我使用了示例,我认为这些代码导致了 Autolayout 异常。

CGFloat height = MAX(0, -y + maxY); CSStickyHeaderFlowLayout.m 中的第 79 行。

如果您对高度使用静态值(例如 200),则该异常将不再发生。我无法理解 UIView-Encapsulated-Layout 到底是什么,但似乎动态更改 UICollectionViewLayoutAttributes 框架可能会导致该问题。在示例项目中,它是高度,在 PO 的问题中,我猜是宽度。如果您认为这会有所帮助,也许我可以深入研究一下

【讨论】:

  • 没错。但是,使用 200 会破坏视差效果。使用 1 而不是 0 似乎可以解决问题。感谢您的帮助。
  • 这不是问题的答案:-(
【解决方案2】:

一个快速而好的解决方法是将999 优先级值分配给具有高优先级的自定义约束。封装和自动生成的约束应该比您的约束具有更高的优先级。

https://stackoverflow.com/a/25795758/590010

【讨论】:

  • 实际上这只是一个快速但不是很好的修复,因为自动生成的约束希望单元格宽度为 0,这不是我想要的。
  • 顺便说一句,如果自定义约束现在的优先级较低,为什么 Auto Layout 根据其较高优先级的系统约束不将标签宽度设置为 0?
  • @Goodsquirrel 你在这方面有什么进展吗?
【解决方案3】:

我可以对问题的答案有所了解。在我的 OS X 应用程序中,我在 NSTableView 的单元格视图(即我之前在 NSTableViewDelegate 方法 -tableView:viewForTableColumn:row 中返回的对象)中发现了这样一个神秘的约束。我还向同一个表列发送了一条 setWidth:0.0 消息。将 setWidth: 中的参数从 0.0 更改为其他值反映在神秘约束的常量值中。

结论:使用“UIView-Encapsulated-Layout-Width”或“NSView-Encapsulated-Layout-Width”记录自身的约束是由设置表格列的宽度或类似内容引起的。

【讨论】:

    【解决方案4】:

    我在 iOS 10 版本中发现了这一点,我将 UITableViewCell 子类用作普通视图而不是表格行。单元格将其 contentView 限制为零宽度。

    我使用的解决方法是将 contentView 添加到视图层次结构而不是 tableview 单元格。我还确保保留 tableView 单元格(因为它不再被视图层次结构本身保留)。

    【讨论】:

      【解决方案5】:

      我的情况

      对我来说,我(从逻辑上)知道我的程序约束应该有效。我在设备旋转后更新它们。

      我在不改变约束的情况下快速简单的解决方案是确保这一切都在主线程上完成。为什么?我不太确定,但我假设轮换更新必须在异步线程中。

      我是如何解决的

      发件人:

      topTitleLeadingAnchorLandscape.isActive = true
      

      收件人:

      DispatchQueue.main.async {
          self.topTitleLeadingAnchorLandscape.isActive = true
      }
      

      希望这可以为将来节省很多时间! ?

      【讨论】:

        【解决方案6】:

        我在添加到NSTableView 的基于NSView 的表格单元格时遇到了这个问题。我在NSView 上设置了一个固定宽度,因为它必须至少是那个大小才能正确容纳内容。但是它可能会更大。

        将宽度约束从 NSLayoutRelationEqual 更改为 NSLayoutRelationGreaterThanOrEqual 消除了警告。

        从此出发:

        [self addConstraint:[NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:panelWidth]];
        

        对此,修复它:

        [self addConstraint:[NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:panelWidth]];
        

        这不是一个 100% 的解决方案,因为当 NSTableView 由于我仍然不清楚的原因决定它需要更小时,它仍然会抛出破坏约束警告。

        【讨论】:

          【解决方案7】:

          我经常遇到这个问题,因为我要求在集合视图(或其父视图之一)实际上是应用程序视图层次结构的一部分之前对其进行布局。基本上发生的情况是这样的:缺少UIWindow 来确定新视图控制器视图的大小,系统将50 点的任意宽度分配给集合的单元格。这通常太小而无法包含其子视图,从而导致约束冲突。

          例如,如果我在viewDidLoad 期间调用layoutIfNeeded,那么视图控制器的视图仍然在没有父级的情况下浮动,并且不知道它有多大。此外,此时无需执行布局,因为无论如何添加到层次结构时布局都会失效并重新计算。

          现在,正如一些人所建议的那样,可以通过将一些约束设为可选但具有非常高的优先级来解决这个问题。这可能是一个有用的通用策略,但在这种情况下可能不是。例如,如果单元格的内容从单元格的侧面插入了一定量,那么只有在内容和单元格的contentView 之间的约束不在所需的优先级时才可能起作用。这会使单元格的大小不明确,并会引发不同的警告。

          在不知道自己在做什么的情况下弄乱约束优先级也会导致无法预料的问题,尤其是当同一轴上的两个约束具有相同的优先级和父级时。堆栈视图的一个常见问题是,当它的子视图在其主轴上都具有相同的优先级时,因此当它不能成为其首选大小时,它无法判断要缩小或扩大哪个。

          在我看来,最好的解决方案是尽量避免在视图添加到其父视图之前对其进行布局。添加一个约束断点并运行应用程序。请注意应用程序因警告而停止的方法;它可能会打电话给layoutIfNeeded。现在,将其替换为以下内容:

          if view.superview != nil {
              view.layoutIfNeeded()
          }
          

          这可能就是您需要做的所有事情。如果您仍然遇到这个问题,那么可能是集合视图的单元格太小了,或者是由于简单的尺寸计算错误、布局对象代码中的问题,或者单元格的约束迫使它成为特定的尺寸,而不是与布局给出的相同。

          【讨论】:

            猜你喜欢
            • 2015-10-09
            • 2021-01-14
            • 2014-06-12
            • 1970-01-01
            • 2021-05-21
            • 2015-06-16
            • 1970-01-01
            • 2015-04-09
            • 2016-03-04
            相关资源
            最近更新 更多