![](/img/trans.png)
[英]Text garbled when using NSTextContainer/NSLayoutManager with UITextView
[英]NSLayoutManager drawGlyphs endless loop when UITextView isScrollingEnabled is false
我有一个自定义的 NSLayoutManager 覆盖了这两种方法:
override func drawGlyphs(forGlyphRange glyphsToShow: NSRange, at origin: CGPoint) {
super.drawGlyphs(forGlyphRange: glyphsToShow, at: origin)
let characterRange = self.characterRange(forGlyphRange: glyphsToShow, actualGlyphRange: nil)
textStorage?.enumerateAttribute(.blur, in: characterRange, options: .longestEffectiveRangeNotRequired, using: { (value, subrange, _) in
guard let key = value as? String, !key.isEmpty else { return }
let blurGlyphRange = glyphRange(forCharacterRange: subrange, actualCharacterRange: nil)
drawBlur(forGlyphRange: blurGlyphRange)
textStorage?.addAttributes([NSAttributedString.Key.foregroundColor: UIColor.clear], range: blurGlyphRange)
})
}
private func drawBlur(forGlyphRange tokenGlypeRange: NSRange) {
guard let textContainer = textContainer(forGlyphAt: tokenGlypeRange.location, effectiveRange: nil) else { return }
let withinRange = NSRange(location: NSNotFound, length: 0)
enumerateEnclosingRects(forGlyphRange: tokenGlypeRange, withinSelectedGlyphRange: withinRange, in: textContainer) { (rect, _) in
let blurRect = rect.offsetBy(dx: self.textContainerOriginOffset.width, dy: self.textContainerOriginOffset.height)
UIColor.red.setFill()
UIBezierPath(roundedRect: blurRect, cornerRadius: 4).fill()
}
一切正常,除了当我将 UITextView isScrollingEnabled 设置为 false 时,我进入了由 drawGlyphs 中的 textStorage enumerateAttribute 方法引起的无限循环。
我不明白为什么会发生这种情况,也不知道如何防止这种情况发生。 有人对此了解更多吗?
编辑
如果我用 foregroundColor 删除 textStorage addAttributes 那么它就可以工作了。 因此,出于某种原因,这导致了循环。
我发现了为什么它会进入和无限循环的问题。 textstorage 更新/添加属性,然后再次通知 layoutmanager。
解决方案是像这样创建自己的文本存储:
class CustomTextStorage: NSTextStorage {
private let backingStore = NSMutableAttributedString()
override var string: String {
return backingStore.string
}
override init() {
super.init()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func attributes(at location: Int, effectiveRange range: NSRangePointer?) -> [NSAttributedString.Key: Any] {
return backingStore.attributes(at: location, effectiveRange: range)
}
override func replaceCharacters(in range: NSRange, with str: String) {
beginEditing()
backingStore.replaceCharacters(in: range, with:str)
edited(.editedCharacters, range: range, changeInLength: (str as NSString).length - range.length)
endEditing()
}
override func setAttributes(_ attrs: [NSAttributedString.Key: Any]?, range: NSRange) {
beginEditing()
backingStore.setAttributes(attrs, range: range)
if let attrs = attrs, let _ = attrs[.blur] {
backingStore.addAttribute(.foregroundColor, value: UIColor.clear, range: range)
}
edited(.editedAttributes, range: range, changeInLength: 0)
endEditing()
}
}
并删除layoutmanager中draw方法下的行:
textStorage?.addAttributes([NSAttributedString.Key.foregroundColor: UIColor.clear], range: blurGlyphRange)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.