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
相关产品推荐
相关产品推荐

