1

I have a SwiftUI Texteditor and whenever I press the update button the color should be applied to the text however it just gets reseted to initialValue. Can anyone help me?

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()
            }
        }
    }

}



0

1 Answer 1

1

When the text of UITextView changes, you never update the @Binding! The binding is not going to know that it is related to the UITextView's text and update itself!

You need to detect the text change of UITextView. You can use UITextViewDelegate to do that. For conforming to that, you need a 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 }
    }

}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.