7

下面最简单的例子。在预览中工作正常(UITextView文本更新为“哎哟”)。但是,在应用程序中运行它(即rootView通过添加 as sceneDelegate),并且UITextView不会更新。

import SwiftUI

class ModelObject : ObservableObject{
    @Published var text = "Model Text"
}

struct MyTextView : UIViewRepresentable {
    @ObservedObject var modelObject : ModelObject

    func makeUIView(context: Context) -> UITextView {
        let result = UITextView()
        result.isEditable = true
        return result
    }
    func updateUIView(_ view: UITextView, context: Context) {
        view.text = modelObject.text
    }
}

struct BugDemoView : View{
    @ObservedObject var modelObject : ModelObject
    var body : some View{
        VStack{
            MyTextView(modelObject: modelObject)
            Button(action: {
                self.modelObject.text = "ouch"
            }){
                Text("Button")
            }
        }
    }
}

#if DEBUG

var mo = ModelObject()

struct BugDemoView_Preview: PreviewProvider {
    static var previews: some View {
        BugDemoView(modelObject: mo)
    }
    
}
#endif
4

4 回答 4

1

它看起来像是 SwiftUI 的某种错误,但有两种解决方法:

  1. 传递字符串 @BindingMyTextView
struct MyTextView : UIViewRepresentable {
    @Binding var text: String

    func makeUIView(context: Context) -> UITextView {
        let result = UITextView()
        result.isEditable = true
        return result
    }
    func updateUIView(_ view: UITextView, context: Context) {
        view.text = text
    }
}

struct BugDemoView : View{
    @ObservedObject var modelObject = ModelObject()
    var body : some View{
        VStack{
            MyTextView(text: $modelObject.text)
            Button(action: {
                self.modelObject.text = "ouch"
            }){
                Text("Button")
            }
        }
    }
}
  1. 将字符串传递给MyTextView
struct MyTextView : UIViewRepresentable {
    var text: String

    func makeUIView(context: Context) -> UITextView {
        let result = UITextView()
        result.isEditable = true
        return result
    }
    func updateUIView(_ view: UITextView, context: Context) {
        view.text = text
    }
}

struct BugDemoView: View{
    @ObservedObject var modelObject = ModelObject()
    var body: some View{
        VStack{
            MyTextView(text: modelObject.text)
            Button(action: {
                self.modelObject.text = "ouch"
            }){
                Text("Button")
            }
        }
    }
}
于 2019-10-14T09:02:16.797 回答
0

我使用以下方法得到了不同的结果。我很确定有一些错误UIViewRepresentable

它适用于某些视图,但随后我再次推送完全相同的视图,并且视图模型不会更新。很奇怪...

希望他们尽快发布 SwiftUI TextView。

struct TextView: UIViewRepresentable {
    @Binding var text: String

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

    func makeUIView(context: Context) -> UITextView {
        let myTextView = UITextView()
        myTextView.delegate = context.coordinator
        myTextView.font = UIFont(name: "HelveticaNeue", size: 15)
        myTextView.isScrollEnabled = true
        myTextView.isEditable = true
        myTextView.isUserInteractionEnabled = true
        myTextView.backgroundColor = UIColor(white: 0.0, alpha: 0.05)
        return myTextView
    }

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

    class Coordinator: NSObject, UITextViewDelegate {

        var parent: TextView

        init(_ uiTextView: TextView) {
            self.parent = uiTextView
        }

        func textViewDidChange(_ textView: UITextView) {
            print("text now: \(String(describing: textView.text!))")
            self.parent.text = textView.text
        }
    }
}
于 2019-11-05T23:33:12.697 回答
0

我通过打印语句注意到在第一个 URL 成功加载后没有再次调用 makeUIView。因此,在 URL 更改后,我的 WebView 仍保留在第一个 URL 上。

我修改了我的 updateUIView 方法——在第一次成功加载后更新 URL 时调用该方法——以检查活动 url 和新 url 之间是否存在差异。如果有区别,我用正确的 url 更新了页面。

这是我的示例 updateUIView 方法:

let request: URLRequest

func updateUIView(_ uiView: WKWebView, context: Context) {
    if uiView.canGoBack, webViewStateModel.goBack {
        uiView.goBack()
        webViewStateModel.goBack = false
    } else {
        if(uiView.url?.absoluteString == request.url?.absoluteString){
            print("The urls are equal")
        } else {
            print("The urls are NOT equal")
            uiView.load(request)
        }
    }
}
于 2021-01-13T06:21:35.140 回答
0

在我的情况下,我需要将一个可观察对象传递给 uiViewRepresentable,因此与 Rivera 提到的情况相同......当该可观察对象的 @Published 属性发生更改时,在模拟器中调用 updateUIView 而不是在真实设备上调用...... . 我正在使用最新的 Xcode 11.4,但不可否认的是在运行 iOS 13.3 的设备上(尚未安装 13.4.1,所以我没有检查该错误是否已消除)。解决我的问题的方法如下:将 struct MyTextView 更改为 final 类(final 关键字很重要),然后添加一个初始化程序。在触发已发布变量的更改之前,甚至不需要对观察到的对象调用 .objectWillChange.send() 。

于 2020-04-15T06:44:15.413 回答