如何修复iOS 11上的UILabel intrinsicContentSize

如何修复iOS 11上的UILabel intrinsicContentSize,ios,iphone,uikit,uilabel,Ios,Iphone,Uikit,Uilabel,在iOS 11上,由于标签明显歪曲了其内在内容大小,我们的许多布局正在崩溃 当一个UILabel被包装在另一个试图实现intrinsicContentSize自身的视图中时,这个错误似乎表现得最糟糕。与此类似(简化和人为示例): UILabel的intrinsicContentSize非常独特,看起来像:(宽度:1073741824.0,高度:20.5)。这会导致布局周期为视图的包装器提供过多的空间 这仅在从XCode 9编译iOS 11时发生。在iOS 10 SDK(在XCode 8上)上编译

在iOS 11上,由于标签明显歪曲了其内在内容大小,我们的许多布局正在崩溃

当一个UILabel被包装在另一个试图实现
intrinsicContentSize
自身的视图中时,这个错误似乎表现得最糟糕。与此类似(简化和人为示例):

UILabel的
intrinsicContentSize
非常独特,看起来像:
(宽度:1073741824.0,高度:20.5)
。这会导致布局周期为视图的包装器提供过多的空间

这仅在从XCode 9编译iOS 11时发生。在iOS 10 SDK(在XCode 8上)上编译的iOS 11上运行时

在XCode 8(iOS 10)上,视图被正确渲染,如下所示:

在XCode 9(iOS 11)上,视图呈现如下:

一个完整的操场代码演示这个问题的要点是


我已经为此申请了一个雷达,并且至少有一个问题的解决方案(见下面的答案)。我想知道是否有其他人遇到过这个问题,或者有其他方法可以尝试。

因此,通过在操场上进行实验,我能够想出一个解决方案,包括测试超大的固有内容大小

我注意到所有行为不端的UILabel都有
numberOfLines==0
preferredMaxLayoutWidth=0
。在随后的布局过程中,UIKit将preferredMaxLayoutWidth设置为非零值,可能是为了迭代到标签的正确高度。因此,第一个修复方法是在
时尝试临时设置
numberOfLines
(self.label.numberOfLines==0&&self.label.preferredMaxLayoutWidth==0)

我还注意到,所有将这两个属性设置为0的UILabel都不一定行为不正常。(也就是说,相反的说法是不正确的)。因此,此修复程序起了作用,但有时不必要地修改了标签。它还有一个小错误,即当标签文本包含
\n
换行符时,行数应设置为字符串中的行数,而不是1

我找到的最后一个解决方案有点老套,但专门针对UILabel的不当行为,只有kick’s it

override var intrinsicContentSize: CGSize {

    guard super.intrinsicContentSize.width > 1000000000.0 else {

        return super.intrinsicContentSize
    }

    var count = 0

    if let text = self.text {

        text.enumerateLines {(_, _) in
            count += 1
        }

    } else {

        count = 1
    }

    let oldNumberOfLines = self.numberOfLines

    self.numberOfLines = count
    let size = super.intrinsicContentSize

    self.numberOfLines = oldNumberOfLines

    return size
}

您可以将此作为要点。

我找到了一个不太老套的解决方案。修复程序正在设置UILabel的
preferredMaxLayoutWidth
。我将其设置为屏幕宽度,如下所示:
preferredMaxLayoutWidth=UIScreen.main.bounds.width
。Hacky macky,它只是工作:拇指支持:@samThis也有同样的效果:很高兴它帮助了@ergunkocak另一个解决方案看起来不错,但我不知道如果像我上面的例子那样提前知道宽度,它是否会工作
override var intrinsicContentSize: CGSize {

    guard super.intrinsicContentSize.width > 1000000000.0 else {

        return super.intrinsicContentSize
    }

    var count = 0

    if let text = self.text {

        text.enumerateLines {(_, _) in
            count += 1
        }

    } else {

        count = 1
    }

    let oldNumberOfLines = self.numberOfLines

    self.numberOfLines = count
    let size = super.intrinsicContentSize

    self.numberOfLines = oldNumberOfLines

    return size
}