SwiftUI UIViewRepresentable UITextView绑定

时间:2020-01-21 11:45:52

标签: swiftui combine

SwiftUI当前不支持多行文本输入(希望很快会添加此功能!),因此我一直在尝试使用Combine框架从UIKit实现不支持多行输入的UITextView,但是我一直在结果不一。

这是我创建的用于创建“文本”视图的代码:

struct MultilineTextView: UIViewRepresentable {

    @Binding var text: String


    func makeUIView(context: Context) -> UITextView {
        let view = UITextView()
        view.isScrollEnabled = true
        view.isEditable = true
        view.isUserInteractionEnabled = true
        view.backgroundColor = UIColor.white
        view.textColor = UIColor.black
        view.font = UIFont.systemFont(ofSize: 17)
        view.delegate = context.coordinator
        return view
    }

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

    func frame(numLines: CGFloat) -> some View {
        let height = UIFont.systemFont(ofSize: 17).lineHeight * numLines
        return self.frame(height: height)
    }

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

    class Coordinator: NSObject, UITextViewDelegate {
        var parent: MultilineTextView

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

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

然后我在swiftUI视图中实现了它,例如:

MultilineTextView(text: title ? $currentItem.titleEnglish : $currentItem.pairArray[currentPair].english)//.frame(numLines: 4)

并将其绑定到状态变量:

@State var currentItem:Item

这类作品。但是,状态var currentItem:Item包含一个字符串数组,然后我使用按钮进行循环浏览,这些按钮根据已输入MultilineTextView的内容更新字符串数组。这是我遇到的问题,其中MultilineTextView似乎仅绑定到数组中的第一个字符串项,然后它不会改变。当我使用swiftUI的本机TextField视图时,此功能可以正常工作,并且我可以遍历字符串数组并通过在TextField中输入文本来更新它。

我认为我必须在MultilineTextView结构中缺少某些东西才能使用此功能。感激地收到了所有指针。

更新:添加了模型结构

struct Item: Identifiable, Codable {
    let id = UUID()
    var completed = false
    var pairArray:[TextPair]
}

struct TextPair: Identifiable, Codable {
    let id = UUID()
    var textOne:String
    var textTwo:String
}

编辑: 因此,我做了更多的挖掘工作,发现了我认为的问题所在。触发UITextView的textViewDidChange时,它会发送更新的文本,我可以在控制台中看到该文本。奇怪的是,updateUIView函数随后也被触发,并且它通过textViewDidChange发送更新之前,使用绑定变量中的内容更新了UITextView的文本。结果是,当您键入UITextview时,它只是拒绝更改。奇怪的是,它适用于数组中的第一个String,但是更改项目后将不再起作用。

2 个答案:

答案 0 :(得分:1)

SwiftUI似乎为每个绑定创建UIViewRepresentable的两个变体,但是在状态(即title被切换时…………)可能由于缺陷而没有切换,值得向苹果公司提交。

我找到了解决方法(已通过Xcode 11.2 / iOS 13.2测试),而是使用如下所示的显式不同视图

if title {
    MultilineTextView(text: $currentItem.titleEnglish)
} else {
    MultilineTextView(text: $currentItem.pairArray[currentPair].textOne)
}

答案 1 :(得分:0)

所以最后我弄清楚了这个问题,之所以没有更新,是因为我传入了一个带有两个状态变量的字符串。您可以在下一行中看到,currentItem是一个状态变量,而currentPair是另一个状态变量,它提供索引号来定位字符串。后者没有被更新,因为它也没有通过绑定传递到多行文本视图中。

MultilineTextView(text: title ? $currentItem.titleEnglish : $currentItem.pairArray[currentPair].english)

我最初认为传递一个是可以的,父视图可以处理另一个,但是事实并非如此。我通过制作两个绑定变量解决了我的问题,因此我可以动态地找到想要的字符串。现在听起来很愚蠢,但当时看不到。