You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift中NSAttributedString含不间断空格多行显示截断问题

解决UILabel显示NSAttributedString时末尾选项被截断的问题

这个问题的核心原因其实有两个:一是你固定了UILabel的高度,导致内容因换行增加高度后,超出部分被直接截断;二是不间断空格的换行逻辑可能让UILabel的尺寸计算出现偏差。下面是具体的解决方法:

1. 移除固定高度约束,让标签高度自适应内容

你当前的代码里把UILabel的高度强制设为和view一样高:

myLabel.heightAnchor.constraint(equalToConstant: self.view.frame.height).isActive = true

这就意味着,不管内容总高度有多高,标签只能显示这么多高度的内容——当填空空格换行导致总内容高度超过view高度时,最后一行选项自然会被切掉。

解决方法很简单:删掉这行固定高度的约束,让UILabel根据内容自动计算高度。如果需要限制标签的最大高度(比如不超出屏幕),可以设置最大高度约束:

// 移除固定高度约束,换成最大高度约束
myLabel.heightAnchor.constraint(lessThanOrEqualToConstant: self.view.frame.height).isActive = true
// 同时让标签内容垂直居中(如果需要)
myLabel.contentMode = .center

2. 优化填空子串的换行逻辑

为了确保不间断空格子串既不被拆分行,又能让UILabel正确计算换行后的尺寸,我们可以给这个子串单独设置段落样式:

// 创建段落样式,确保不间断空格不被拆分
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineBreakMode = .byWordWrapping
paragraphStyle.allowsDefaultLineBreakBefore = false // 禁止默认的换行前置逻辑

// 给填空子串添加段落样式
myAttributedText.addAttribute(.paragraphStyle, value: paragraphStyle, range: (myText as NSString).range(of: underlineString))

3. 强制标签重新计算尺寸

在设置完attributedText后,强制UILabel刷新布局,确保它根据最新的内容重新计算尺寸:

myLabel.attributedText = myAttributedText
myLabel.invalidateIntrinsicContentSize() // 刷新固有内容尺寸
myLabel.layoutIfNeeded() // 立即更新布局

替代方案:用自定义宽度的占位符替代不间断空格

如果你想更精准控制填空的宽度,避免空格数量带来的换行不确定性,可以用字距调整+单个空格来创建固定宽度的下划线占位:

let font = UIFont(name: "My Font", size: round(self.view.frame.width / 15))!
let placeholderWidth = font.pointSize * 3 // 自定义宽度,比如3个字符宽
// 通过kern(字距)调整单个空格的宽度到目标值
let placeholderAttributes: [NSAttributedString.Key: Any] = [
    .font: font,
    .foregroundColor: UIColor(white: 1, alpha: 0.9),
    .underlineStyle: NSUnderlineStyle.styleThick.rawValue,
    .kern: placeholderWidth - font.pointSize
]
let placeholderString = NSAttributedString(string: " ", attributes: placeholderAttributes)

// 替换原文本中的空格子串
let baseText = "What do you think about  and then what about this extra stuff at the end?\na) first choice\nb) second choice\nc) last choice"
let mutableText = NSMutableAttributedString(string: baseText, attributes: myTextAttributes)
// 找到" "的位置替换成占位符
let range = (baseText as NSString).range(of: " ")
mutableText.replaceCharacters(in: range, with: placeholderString)
myLabel.attributedText = mutableText

这样既可以实现固定宽度的下划线填空,又能避免不间断空格带来的换行计算问题。


内容的提问来源于stack exchange,提问作者Damien X

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:21:39