Xcode 11.2 之后:应用因 _UITextLayoutView 崩溃 — 解决方案

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

更新 Xcode 11.2 后应用崩溃:如何战胜 _UITextLayoutView



有没有遇到过这种情况:你正平静地开发项目,一切运行流畅,测试通过,用户满意。然后——砰!——你将 Xcode 更新到 11.2 版本,启动应用,它却因一个神秘的错误 _UITextLayoutView 而崩溃。熟悉吗?如果是——你并不孤单。这个问题在 2019 年底几乎引爆了 Stack Overflow(一周内数千次浏览)。



在这篇文章中,我不仅会展示如何修复这个错误,还会解释它为什么发生,如何诊断,以及最重要的是,如何在未来避免。我们将用 Swift 的实际例子来全面分析。开始吧!



_UITextLayoutView 到底是什么?



从理论开始。_UITextLayoutView 是 UIKit 的一个内部(私有)类,负责 UITextView 中的文本渲染。Apple 没有公开记录它,因此当 Xcode 11.2 中这个类出现问题时,开发者们陷入了困境。错误看起来像这样:



*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[_UITextLayoutView setFrame:]: unrecognized selector sent to instance 0x...'


关键短语是 "unrecognized selector sent to instance"。这意味着你试图在一个不支持该方法的对象上调用 setFrame: 方法。由于 _UITextLayoutView 是一个私有类,在 Xcode 11.2 之前它的行为是不同的。



谁处于风险中?



这个问题并非出现在所有人身上,只在特定条件下出现。这是一个典型场景:

  • 你使用启用了自动调整大小(auto-sizing)的 UITextView。
  • 你有一个自定义的视图层次结构,其中 UITextView 嵌套在 UIScrollView 或 UITableViewCell 中。
  • 你频繁与文本字段交互:滚动、编辑、更改字体。


如果至少有一项符合——恭喜,你处于风险区。但别担心:解决方案是存在的,而且很优雅。



步骤 1:诊断——找到罪魁祸首



在治疗之前,让我们确认问题确实出在 _UITextLayoutView 上。打开 Xcode 控制台(View → Debug Area → Activate Console)并启动应用。如果你看到类似我上面提到的错误——你就找对方向了。



额外迹象:崩溃发生在首次尝试显示 UITextView 或在其内部滚动时。如果应用在加载后立即崩溃——很可能就是这个原因。



步骤 2:简单快速的解决方案(适合赶时间的人)



Stack Overflow 上最流行的修复方法是禁用 UITextView 的自动调整大小。操作方法如下:



// 在你的 viewDidLoad 或配置方法中textView.isScrollEnabled = falsetextView.translatesAutoresizingMaskIntoConstraints = true


但注意!这个方案有效,但它会破坏文本的自动大小。如果你需要 UITextView 根据内容动态改变高度——这种方法就不适用了。让我们深入挖掘。



步骤 3:高级解决方案——重写 layoutSubviews



Apple 在 Xcode 11.2.1 中发布了补丁,但如果你因某些原因仍在使用 11.2,或者想要一个通用解决方案,下面是需要做的。



创建一个 UITextView 的子类并重写 layoutSubviews 方法:



import UIKit

class FixedTextView: UITextView { override func layoutSubviews() { super.layoutSubviews() // 清除由错误引起的多余子视图层 self.subviews.forEach { subview in if subview.isKind(of: NSClassFromString("_UITextLayoutView") ?? UIView.self) {

博客

书籍推荐