我有一个 SwiftUI 文本编辑器,每当我按下更新按钮时,颜色应该应用于文本,但它只是重置为初始值。有人可以帮助我吗?
import SwiftUI
class TextColorUpdater: ObservableObject {
@Published var attributedText: NSAttributedString
init(initialText: String) {
self.attributedText = TextColorUpdater.highlightText(initialText)
}
func update() {
print(attributedText.string)
self.attributedText = TextColorUpdater.highlightText(attributedText.string)
}
static func highlightText(_ text: String) -> NSAttributedString {
let mutableAttributedString = NSMutableAttributedString(string: text)
if let regex = try? NSRegularExpression(pattern: "\\bred\\b", options: .caseInsensitive) {
let matches = regex.matches(in: text, options: [], range: NSRange(location: 0, length: text.utf16.count))
for match in matches {
let nsRange = match.range
mutableAttributedString.addAttribute(.foregroundColor, value: UIColor.red, range: nsRange)
}
}
return mutableAttributedString
}
}
struct HighlightedTextEditor: UIViewRepresentable {
@Binding var attributedText: NSAttributedString
func makeUIView(context: Context) -> UITextView {
let textView = UITextView()
textView.isEditable = true
textView.isSelectable = true
return textView
}
func updateUIView(_ uiView: UITextView, context: Context) {
uiView.attributedText = attributedText
}
}
struct ContentView: View {
@StateObject var textColorUpdater = TextColorUpdater(initialText: "This is a redd red red red car. The sky is not red")
var body: some View {
VStack {
HighlightedTextEditor(attributedText: $textColorUpdater.attributedText)
Button("Update") {
textColorUpdater.update()
}
}
}
}
当
UITextView
的文本发生变化时,你永远不会更新@Binding
!绑定不会知道它与 UITextView
的文本相关并自行更新!
您需要检测
UITextView
的文本变化。您可以使用 UITextViewDelegate
来做到这一点。为了符合这一点,您需要一个 Coordinator
。
struct HighlightedTextEditor: UIViewRepresentable {
@Binding var attributedText: NSAttributedString
@MainActor
class Coordinator: NSObject, UITextViewDelegate {
let textView = UITextView()
var textDidChange: ((NSAttributedString) -> Void)?
override init() {
textView.isEditable = true
textView.isSelectable = true
super.init()
textView.delegate = self
}
func textViewDidChange(_ textView: UITextView) {
textDidChange?(textView.attributedText)
}
}
func makeUIView(context: Context) -> UITextView {
context.coordinator.textView
}
func makeCoordinator() -> Coordinator {
Coordinator()
}
func updateUIView(_ uiView: UITextView, context: Context) {
uiView.attributedText = attributedText
context.coordinator.textDidChange = { attributedText = $0 }
}
}