SwiftUI 封装的 UITextView 未更新 ObservedObject。

4

我希望我是错的,但我找不到SwiftUI中可编辑UITextView的等效物。因此,我使用UIViewRepresentable构建了一个。使用ObservableObject填充SwiftUI文本和我的视图都可以工作 - 但在我的视图中进行的更新没有传播到ObservableObject。我一定漏掉了与Binding概念有关的重要内容。如果有任何指导,将不胜感激。

import SwiftUI
import Combine

struct ContentView: View {

    @ObservedObject var myOText: MyOText

    var body: some View {
        ScrollView {
            VStack {
                Text("This is a bound Text View")
                    .padding(.top, 10)
                    .font(.headline)

                Text(myOText.inTheCourse)
                    .lineLimit(3)
                    .padding()

                Text("This is a multi-line UITextView wrapper:")
                    .font(.headline)

                MultilineTextView(myOText: myOText)
                    .frame(height: 100)
                    .padding()

                Spacer()
            }
        }
    }
}

struct MultilineTextView: UIViewRepresentable {

    @ObservedObject var myOText: MyOText

    func makeUIView(context: Context) -> UITextView {
        let view = UITextView()
        view.isScrollEnabled = true
        view.isEditable = true
        view.isUserInteractionEnabled = true
        view.textAlignment = .center
        view.font = UIFont(name: "Times New Roman", size: 20)
        return view
    }

    func updateUIView(_ uiView: UITextView, context: Context) {
        uiView.text = myOText.inTheCourse
    }
}

class MyOText: ObservableObject {
    @Published var inTheCourse: String = "When in the Course of human events, it becomes necessary for one people to dissolve the political bands which have connected them ..."
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView(myOText: MyOText())
    }
}

enter image description here Xcode 11.2 beta 2 (11B44)版本,iOS 13。


更改 inTheCourse 是否会传播到您的 UIKit 视图?我之所以问,是因为在我的情况下,在我的 @ObservedObject 中进行更改不会触发 updateUIViewController(在我的情况下使用 UIViewControllerRepresentable)。 - Rivera
我没有那样使用它。我将myOText保存到Core Data中,然后从Core Data中加载。但是,我进行了一个简化的测试,使用一个myOText、一个TextField和一个TextView,它们都连接到ObservedObject,当在TextField中输入时,会更新TextView,但不会更新myOText——就像你所建议的那样。一定有办法指示协调器这样做。也许Jeff或其他人可以发表评论。 - JohnSF
1个回答

6
您的多行文本视图需要一个协调器来观察UITextView中文本的更新。
struct MultilineTextView: UIViewRepresentable {
    @ObservedObject var myOText: MyOText

    func makeUIView(context: Context) -> UITextView {
        let view = UITextView()
        view.isScrollEnabled = true
        view.isEditable = true
        view.isUserInteractionEnabled = true
        view.textAlignment = .center
        view.font = UIFont(name: "Times New Roman", size: 20)
        view.delegate = context.coordinator
        return view
    }

    func updateUIView(_ uiView: UITextView, context: Context) {
        uiView.text = myOText.inTheCourse
    }

    func makeCoordinator() -> MultilineTextView.Coordinator {
        Coordinator(self)
    }

    class Coordinator: NSObject, UITextViewDelegate {
        var control: MultilineTextView

        init(_ control: MultilineTextView) {
            self.control = control
        }

        func textViewDidChange(_ textView: UITextView) {
            control.myOText.inTheCourse = textView.text
        }
    }
}

太棒了。像冠军一样运作。 - JohnSF
1
很奇怪,但是以这种方式包装的UITextView会在按下回车键时将光标跳到整个文本的末尾。同样,在空行上按退格键时,它也会跳到文本的末尾。 - Munhitsu
@jeff,我该如何让默认文本(灰色)显示出来,一旦用户输入自己的文本,就会被常规的黑色文本替换,如果他们删除文本,则反之亦然? - Learn2Code
@Munhitsu 我也遇到了光标跳动的问题,并在我的 updateUIView 中通过仅在 UITextView 的文本更改时更新它来解决了这个问题。 - Mark Krenek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接