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

NSTextView设置.ligature属性时被.paragraphStyle与.baselineOffset覆盖问题咨询

在NSTextView中同时设置连字、段落样式与基线偏移时的连字失效问题

问题详情

给NSTextView的textStorage设置属性时,若同时添加.ligature: 0(用于禁用FiraCode字体自带的连字效果)、自定义.paragraphStyle(控制行间距)和.baselineOffset,会出现连字属性被意外覆盖的情况——连字无法被禁用。

只有移除.font属性时,连字才能成功禁用;但如果移除.paragraphStyle和.baselineOffset,连字虽能禁用,却会丢失所需的行间距。

示例代码:

textView.textStorage?.setAttributes(
    [
        .ligature: 0,
        .font: NSFont(name: "FiraCode-Light", size: 12)!,
        .baselineOffset: 3.5,
        .paragraphStyle: {
            let p = NSParagraphStyle.default.mutableCopy() as! NSMutableParagraphStyle
            p.lineHeightMultiple = 1.5
            p.lineSpacing = 10
            return p
        }()
    ],
    range: NSRange(location: 0, length: self.textView.string.count)
)

连字错误启用的效果:
连字错误启用效果

连字禁用但行间距丢失的效果:
连字禁用但行间距丢失效果

解决方案

这并非Apple的代码bug,而是属性设置优先级与字体默认属性继承导致的问题。正确的处理方式是分步设置属性,确保连字属性能覆盖字体的默认设置:

方法一:分步调用属性设置API

// 先设置基础样式:字体、段落样式、基线偏移
let paragraphStyle: NSMutableParagraphStyle = {
    let p = NSParagraphStyle.default.mutableCopy() as! NSMutableParagraphStyle
    p.lineHeightMultiple = 1.5
    p.lineSpacing = 10
    return p
}()

textView.textStorage?.setAttributes(
    [
        .font: NSFont(name: "FiraCode-Light", size: 12)!,
        .baselineOffset: 3.5,
        .paragraphStyle: paragraphStyle
    ],
    range: NSRange(location: 0, length: textView.string.count)
)

// 单独设置连字属性,确保覆盖字体默认值
textView.textStorage?.addAttribute(.ligature, value: 0, range: NSRange(location: 0, length: textView.string.count))

方法二:使用NSMutableAttributedString构建完整属性字符串

let attrString = NSMutableAttributedString(string: textView.string)
let fullRange = NSRange(location: 0, length: attrString.length)

// 先设置字体、段落样式和基线偏移
let paragraphStyle: NSMutableParagraphStyle = {
    let p = NSParagraphStyle.default.mutableCopy() as! NSMutableParagraphStyle
    p.lineHeightMultiple = 1.5
    p.lineSpacing = 10
    return p
}()
attrString.addAttributes(
    [
        .font: NSFont(name: "FiraCode-Light", size: 12)!,
        .baselineOffset: 3.5,
        .paragraphStyle: paragraphStyle
    ],
    range: fullRange
)

// 单独追加连字属性
attrString.addAttribute(.ligature, value: 0, range: fullRange)

// 赋值给textStorage
textView.textStorage?.setAttributedString(attrString)

原理说明

FiraCode字体默认启用连字效果,当一次性批量设置所有属性时,字体自带的默认连字属性优先级可能高于手动设置的.ligature: 0。通过分步设置,先应用字体等基础属性,再单独设置连字,能确保连字属性覆盖字体默认值,同时保留段落样式与基线偏移的效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 03:05:41