我发现比NSLayoutManager
的showsInvisibleCharacters
属性设置为true
,通过继承NSLayoutManager
和覆盖方法drawBackgroundForGlyphRange(NSRange, CGPoint)
,这允许针对每个空白字符定制附图中,例如更好的解决方案:
class LayoutManager : NSLayoutManager {
var text: String? { return textStorage?.string }
var font: UIFont = UIFont.systemFontOfSize(UIFont.systemFontSize()) {
didSet {
guard let text = self.text else { return }
let textRange = NSMakeRange(0, (text as NSString).length)
invalidateGlyphsForCharactersInRange(textRange, actualCharacterRange: nil)
invalidateCharacterAttributesForCharactersInRange(textRange, actualCharacterRange: nil)
}
}
override func drawBackgroundForGlyphRange(glyphsToShow: NSRange, atPoint origin: CGPoint) {
super.drawBackgroundForGlyphRange(glyphsToShow, atPoint:origin)
guard let text = self.text else { return }
enumerateLineFragmentsForGlyphRange(glyphsToShow)
{ (rect: CGRect, usedRect: CGRect, textContainer: NSTextContainer, glyphRange: NSRange, stop: UnsafeMutablePointer<ObjCBool>) -> Void in
let characterRange = self.characterRangeForGlyphRange(glyphRange, actualGlyphRange: nil)
// Draw invisible tab space characters
let line = (self.text as NSString).substringWithRange(characterRange)
do {
let expr = try NSRegularExpression(pattern: "\t", options: [])
expr.enumerateMatchesInString(line, options: [.ReportProgress], range: line.range)
{ (result: NSTextCheckingResult?, flags: NSMatchingFlags, stop: UnsafeMutablePointer<ObjCBool>) in
if let result = result {
let range = NSMakeRange(result.range.location + characterRange.location, result.range.length)
let characterRect = self.boundingRectForGlyphRange(range, inTextContainer: textContainer)
let symbol = "\u{21E5}"
let attrs = [NSFontAttributeName : Font]
let height = (symbol as NSString).sizeWithAttributes(attrs).height
symbol.drawInRect(CGRectOffset(characterRect, 1.0, height * 0.5, withAttributes: attrs)
}
}
} catch let error as NSError {
print(error.localizedDescription)
}
}
}
}
阅读苹果关于文本布局系统的文档。文本编辑不是一个简单的主题,涉及到很多类,如NSLayoutManager,NSTextView,NSTextContainer,NSTypeSetter。已经有一段时间了,但你可能需要一个自定义的NSLayoutManager(在iOS上)或一个自定义的NSTypeSetter(在OS X上)。 用自定义(可见)字符替换不可见字符当然是可行的,但它不像在NSTextView中重写drawRect那么简单。 – user965972
@ user965972我已经有了一个自定义的NSLayoutManager和自定义的NSTextStorage,它为文本视图启用行编号和压缩行的缩进。我对Text Kit非常熟悉,但是我希望有人能够给我一个提示,告诉我在生产中用于自定义绘制空白字符图形的最可接受的做法 –
在这种情况下:布局管理器具有从字符生成NSGlyphs的功能(尽管这不是一对一的关系)。重写其中一个函数来为自定义的NSGlyph注入一个空格字符。 你不必自己做任何绘画。您只需指定文字系统应绘制哪个字形。 – user965972