SwiftUI UIViewRepresentable UITextView绑定 [英] SwiftUI UIViewRepresentable UITextView Binding

查看:76
本文介绍了SwiftUI UIViewRepresentable UITextView绑定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Multiline text input is currently not natively supported in SwiftUI (hopefully this feature is added soon!) so I've been trying to use the combine framework to implement a UITextView from UIKit which does support multiline input, however i've been having mixed results.

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

This is the code i've created to make the Text view:

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视图中实现了它,例如:

I've then implemented it in a swiftUI view like:

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

并将其绑定到状态变量:

And bound it to a state variable:

@State var currentItem:Item

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

It sort of works. However, the state var currentItem:Item contains an array of strings which I'm then cycling through using buttons which update the string array based on what has been inputted into MultilineTextView. This is where i'm encountering a problem where the MultilineTextView seems to bind to only the first string item in the array, and then it won't change. When I use swiftUI's native TextField view this functionality works fine and I can cycle through the string array and update it by inputting text into the TextField.

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

I think I must be missing something in the MultilineTextView struct to allow this functionality. Any pointers are gratefully received.

更新:添加了模型结构

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,但是更改项目后将不再起作用.

So I've done some more digging and I've found what I think is the problem. When the textViewDidChange of the UITextView is triggered, it does send the updated text which I can see in the console. The strange thing is that the updateUIView function then also gets triggered and it updates the UITextView's text with what was in the binding var before the update was sent via textViewDidChange. The result is that the UITextview just refuses to change when you type into it. The strange thing is that it works for the first String in the array, but when the item is changed it won't work anymore.

推荐答案

看来,SwiftUI为每个绑定创建了 UIViewRepresentable 的两个变体,但是在状态时不会切换它们,即标题已被切换...可能是由于缺陷所致,值得提交给Apple.

It appears that SwiftUI creates two variants of UIViewRepresentable, for each binding, but does not switch them when state, ie title is switched... probably due to defect, worth submitting to Apple.

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

I've found worked workaround (tested with Xcode 11.2 / iOS 13.2), use instead explicitly different views as below

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

这篇关于SwiftUI UIViewRepresentable UITextView绑定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆