iPhone14Pro/15系列UITextView无法显示最后一行问题求助
问题背景
iOS 16之后UITextView默认使用TextKit2,存在布局bug时可通过usingTextLayoutManager: false回退到TextKit1,但在iPhone 14 Pro、15及15 Pro机型上,即使使用该初始化方式,UITextView仍无法显示最后一行;开启TextKit2时问题同样存在。目前临时解决方案是在文本末尾加\n,但会产生多余空白影响美观。
自定义UITextView的配置代码如下:
contentText?.labled() contentText?.style(5, UIFont.systemFont(ofSize: 17.scaled()))
func labled() { self.isSelectable = true self.isEditable = false self.isScrollEnabled = false self.showsVerticalScrollIndicator = false self.showsHorizontalScrollIndicator = false self.textContainer.lineFragmentPadding = 0 self.textContainerInset = .zero self.translatesAutoresizingMaskIntoConstraints = false self.textAlignment = .left } func style(_ space:CGFloat,_ font:UIFont) { let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.lineSpacing = space.scaled() let attributes = [NSAttributedString.Key.paragraphStyle: paragraphStyle, NSAttributedString.Key.font: font] self.typingAttributes = attributes }
可能的修复方案
1. 替换typingAttributes为直接设置attributedText
typingAttributes仅作用于用户输入的新文本,对已设置的普通文本/富文本不生效。应该直接给attributedText赋值并附带样式:
// 假设你的原始文本是originalText let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.lineSpacing = 5.scaled() let attributes = [NSAttributedString.Key.paragraphStyle: paragraphStyle, NSAttributedString.Key.font: UIFont.systemFont(ofSize: 17.scaled())] contentText?.attributedText = NSAttributedString(string: originalText, attributes: attributes)
同时可以移除原来的style方法,避免混淆。
2. 给textContainerInset添加极小的底部内边距
不需要添加额外换行,仅给textContainerInset设置一个1pt的底部内边距,既不会产生明显空白,又能让最后一行完整显示:
// 在labled()方法中修改 self.textContainerInset = UIEdgeInsets(top: 0, left: 0, bottom: 1, right: 0)
3. 强制文本布局更新
在设置文本后手动触发布局更新,确保TextKit正确计算高度:
contentText?.text = originalText contentText?.layoutIfNeeded() // 或者强制更新文本容器 contentText?.textContainer.layoutManager?.ensureLayout(for: contentText?.textContainer ?? NSTextContainer())
4. 检查自适应高度约束
如果UITextView使用自适应高度约束(比如通过sizeToFit()或自动布局的高度约束),确保约束优先级正确,且没有被其他约束覆盖。可以尝试将高度约束的优先级设为UILayoutPriority.defaultHigh,并在设置文本后调用invalidateIntrinsicContentSize():
contentText?.text = originalText contentText?.invalidateIntrinsicContentSize()
补充说明
目前没有明确证据表明Apple在这些机型上强制使用TextKit2,上述方案均能绕过最后一行不显示的布局bug。其中方案2实现成本最低,且对视觉影响可以忽略;方案1能确保文本样式正确应用,适合需要精确控制富文本的场景。
内容的提问来源于stack exchange,提问作者user23345662

