我的 SwiftUI 应用中有一个自定义UITextView
。UIViewRepresentable
使用 TextKit2,我确定了要进行绘制的区域。
一切工作正常,除了当我旋转设备(模拟器或预览)时,绘图没有更新。
旋转前:
旋转后:
我发现,当我点击方向两次时,确实会发生重绘:
我错过了什么?
以下是一份 MRE:
import SwiftUI
struct ContentView: View {
var body: some View {
TextViewRepresentable()
}
}
#Preview {
ContentView()
}
struct TextViewRepresentable: UIViewRepresentable {
let alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
func makeUIView(context: Context) -> UITextView {
let textView = UITextView()
let tc = NSTextContainer(size: textView.textContainer.size)
tc.heightTracksTextView = true
tc.widthTracksTextView = true
let lm = NSTextLayoutManager()
lm.textContainer = tc
let ts = NSTextContentStorage()
ts.addTextLayoutManager(lm)
let myTextView = MyTextView(frame: textView.frame, textContainer: tc)
myTextView.font = UIFont.monospacedSystemFont(ofSize: 44, weight: .regular)
return myTextView
}
func updateUIView(_ uiView: UITextView, context: Context) {
uiView.text = alphabet + alphabet
}
}
class MyTextView: UITextView {
override func draw(_ rect: CGRect) {
super.draw(rect)
debugPrint("draw")
guard let context = UIGraphicsGetCurrentContext() else { return }
context.setFillColor(red: 1.0, green: 0.0, blue: 0.0, alpha: 1.0)
for rect in rects(for: NSMakeRange(3, 12)) {
context.fill(rect)
}
}
func rects(for range: NSRange) -> [CGRect] {
var rects: [CGRect] = []
if let textLayoutManager = textLayoutManager, let contentManager = textLayoutManager.textContentManager {
guard let start = contentManager.location(contentManager.documentRange.location, offsetBy: range.location),
let end = contentManager.location(start, offsetBy: range.length),
let textRange = NSTextRange(location: start, end: end)
else {
return []
}
textLayoutManager.enumerateTextSegments(in: textRange, type: .standard, options: .rangeNotRequired) { _, rect, _, _ in
var adjustedRect = rect
adjustedRect.size.height -= CGFloat(4.0)
adjustedRect = CGRectOffset(rect, 0, CGFloat(8.0))
rects.append(adjustedRect)
return true
}
}
return rects
}
}
似乎你只是想
draw
在框架发生MyTextView
变化时再次被调用。你可以将其设置contentMode
为.redraw
: