下面是最简单的示例。在预览中工作正常(UITextView文本更新为“ ouch”)。但是,在应用程序中运行它(例如,由sceneDelegate添加为rootView),UITextView不会更新。
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
答案 0 :(得分:0)
它看起来像是SwiftUI的某种错误,但是有两种解决方法:
@Binding
传递到MyTextView
: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")
}
}
}
}
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")
}
}
}
}
答案 1 :(得分: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
}
}
}
答案 2 :(得分:0)
在我的情况下,我需要将一个可观察对象传递给uiViewRepresentable,因此与Rivera提到的情况相同...当该可观察对象的@Published属性发生更改时,会在模拟器中调用updateUIView,而不是在真实对象上调用设备...我使用的是最新的Xcode 11.4,但是请注意,该设备是在运行iOS 13.3的设备上安装的(尚未安装13.4.1,因此我尚未检查该错误是否已消除)。解决我的问题的方法如下:将结构MyTextView更改为final类(final关键字很重要),然后添加一个初始化程序。甚至不必在触发已发布的var的更改之前就在观察的对象上调用.objectWillChange.send()。
答案 3 :(得分:0)
我通过打印语句注意到在第一个 URL 成功加载后没有再次调用 makeUIView。因此,在更改 URL 时,我的 WebView 仍保留在第一个 URL 上。
我修改了我的 updateUIView 方法 - 在第一次成功加载后更新 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)
}
}
}