我试图在我的NSTextView子类中显示不可见字符,如新行字符。像重写NSLayoutManager的drawGlyph方法这样的常用方法是一个坏主意,因为它太慢,并且不适合多页面布局。NSLayoutManager隐藏新行字符不管我做什么
我想要做的是重写NSLayoutManager的setGlyph方法,以便用“¶”字形替换不可见的“\ n”字形并用“∙”替换“”。
它对“”空格字形起作用,但对新行字符没有影响。
public override func setGlyphs(_ glyphs: UnsafePointer<CGGlyph>, properties props: UnsafePointer<NSGlyphProperty>, characterIndexes charIndexes: UnsafePointer<Int>, font aFont: Font, forGlyphRange glyphRange: NSRange) {
var substring = (self.currentTextStorage.string as NSString).substring(with: glyphRange)
// replace invisible characters with visible
if PreferencesManager.shared.shouldShowInvisibles == true {
substring = substring.replacingOccurrences(of: " ", with: "\u{00B7}")
substring = substring.replacingOccurrences(of: "\n", with: "u{00B6}")
}
// create a CFString
let stringRef = substring as CFString
let count = CFStringGetLength(stringRef)
// convert processed string to the C-pointer
let cfRange = CFRangeMake(0, count)
let fontRef = CTFontCreateWithName(aFont.fontName as CFString?, aFont.pointSize, nil)
let characters = UnsafeMutablePointer<UniChar>.allocate(capacity: MemoryLayout<UniChar>.size * count)
CFStringGetCharacters(stringRef, cfRange, characters)
// get glyphs for the pointer of characters
let glyphsRef = UnsafeMutablePointer<CGGlyph>.allocate(capacity: MemoryLayout<CGGlyph>.size * count)
CTFontGetGlyphsForCharacters(fontRef, characters, glyphsRef, count)
// set those glyphs
super.setGlyphs(glyphsRef, properties:props, characterIndexes: charIndexes, font: aFont, forGlyphRange: glyphRange)
}
于是我想出了一个主意:它看起来像NSTypesetter标志着新行字符范围像那些它不应该处理的。因此,我将NSTypesetter分类并重写了一种方法:
override func setNotShownAttribute(_ flag: Bool, forGlyphRange glyphRange: NSRange) {
let theFlag = PreferencesManager.shared.shouldShowInvisibles == true ? false : true
super.setNotShownAttribute(theFlag, forGlyphRange: glyphRange)
}
但它不起作用。无论我创建的是什么字形,NSLayoutManager仍然不会为新行字符生成字形。
我在做什么错?
似乎这段代码在Swift3中,我们如何将它转换成Swift 2.3?我注意到Swift 2.3中没有“MemoryLayout”。 –