onmyway133 / blog

🍁 What you don't know is what you haven't learned
https://onmyway133.com/
MIT License
674 stars 33 forks source link

How to use UITextView in SwiftUI #747

Open onmyway133 opened 3 years ago

onmyway133 commented 3 years ago

Need to use Coordinator conforming to UITextViewDelegate to apply changes back to Binding

import SwiftUI
import UIKit

struct MyTextView: UIViewRepresentable {
    @Binding
    var text: String

    final class Coordinator: NSObject, UITextViewDelegate {
        let parent: MyTextView

        init(parent: MyTextView) {
            self.parent = parent
        }

        func textViewDidChange(_ textView: UITextView) {
            if textView.text != parent.text {
                parent.text = textView.text
            }
        }
    }

    func makeCoordinator() -> Coordinator {
        Coordinator(parent: self)
    }

    func makeUIView(context: Context) -> UITextView {
        let view = UITextView()
        view.isScrollEnabled = true
        view.isEditable = true
        view.isUserInteractionEnabled = true
        view.font = UIFont.preferredFont(forTextStyle: .body)
        view.delegate = context.coordinator
        return view
    }

    func updateUIView(_ uiView: UITextView, context: Context) {
        uiView.text = text
    }
}
NickAtGit commented 2 years ago

Hey man, I'm using pretty much the same pattern for my TextView. There is one big problem that isn't visible in first place. When you wrote some text and then you want to edit in the middle of the text the cursor jumps to the end of the text after every typed character. The culprit in this case is textViewDidChange. Do you have a solution for that?