【问题标题】:SwiftUI = UIViewControllerRepresentable Update Text via @BindingSwiftUI = UIViewControllerRepresentable 通过@Binding 更新文本
【发布时间】:2020-03-22 02:01:00
【问题描述】:

在 SwiftUI 中,我尝试使用按钮在 UIViewControllerRepresentable 中实现文本更改,但可能缺少关于绑定的关键概念。

在 SwiftUI 中:

struct MainView: View {
 @State private var textHere = "Set up text"
  var body: some View {
   return VStack{
    DisplayView(text: $textHere)
    Button(action:{
     self.textHere = "Button update text" 
    }) {
     HStack {
      Text("Change the text by clicking")
      .background(Color.white)
     }
    }
    .background(Color.blue)
   }
  }
}

然后我有一个 UIViewControllerRepresentable:

struct DisplayView: UIViewControllerRepresentable  {
 @Binding var text: String

  func makeUIViewController(context: UIViewControllerRepresentableContext< DisplayView >) -> UIViewController {
   let controller = DisplayViewController()
   controller.text = text
   return controller
  }

  func updateUIViewController(_ uiViewController: UIViewController, context: UIViewControllerRepresentableContext< DisplayView >) {
   let controller = DisplayViewController()
   controller.text = text
   controller.updateText()
  }
}

我的视图控制器:

class CameraViewController : UIViewController {
 var text = "Hello"
 var textViewTest = UILabel()

 func updateText(){
  print("update text " + text)
  self.textViewTest = UILabel(frame: CGRect(x: 40.0, y: 120.0, width: 250.0, height: 100.0))
  ...
  self.textViewTest.text = text
 }

 override func viewDidLoad() {
  super.viewDidLoad()
  self.textViewTest = UILabel(frame: CGRect(x: 40.0, y: 120.0, width: 250.0, height: 100.0))
  ...
  self.textViewTest.text = text
  view.addSubview(self.textViewTest)
 }
}

我在 updateText() 函数中尝试了一些变体。

数据正在通过按钮单击传递:

  • “按钮更新文本”传入UIViewControllerRepresentable的updateUIViewController方法中
  • “按钮更新文本”被传递到 UIViewController
  • “按钮更新文本”传入UIViewController的viewDidLoad

但是传递的值不会显示为标签上的更改。

似乎有可能在 ViewController 中进行了更新,但 SwiftUI 视图没有更新?

编辑:

This article 将我指向“包装”UIRepresentable 的方向。这是新版本:

    struct DisplayView: UIViewControllerRepresentable  {
     typealias UIViewControllerType = CameraViewController
     var text: String?

     func makeUIViewController(context: UIViewControllerRepresentableContext< DisplayView >) -> CameraViewController {
      print("view called")
      return CameraViewController()
     }

     func updateUIViewController(_ cameraViewController: CameraViewController, context: UIViewControllerRepresentableContext< DisplayView >) {
      print("View updated")
      cameraViewController.text = text
     }
    }

并且 ViewController 已经更新:

final class CameraViewController : UIViewController {
 var text: String? {
  didSet {
   updateController()
  }
 }

 private var ccmeraViewController: CameraViewController?

 func updateController(){
  let textViewTest = UILabel(frame: CGRect(x: 40.0, y: 120.0, width: 250.0, height: 100.0))
  guard let text = text else { return }

  textViewTest.center = self.view.center
  textViewTest.textAlignment = NSTextAlignment.justified
  textViewTest.textColor = UIColor.blue
  textViewTest.backgroundColor = UIColor.lightGray
  textViewTest.text = text
  view.addSubview(textViewTest)
 }

 override func viewDidLoad() {
  super.viewDidLoad()
  //updateController()
 }

一切都很好!我们现在可以正确地将一个字符串值从 SwiftUI 传递给 ViewController 并更新标签。

但是,当您第一次打开页面时,makeUIViewController 和 updateUIViewController 都会被调用,因此标签的两个实例会彼此重叠。

所以最后一步是弄清楚如何只显示一次 UILabel。

更新 3 和部分解决方案

具有解决方案can be found here 的最小存储库。

答案是正确的,你需要添加@Binding。然而,有趣的是,将 String 绑定到显示标签的 ViewController 会导致视图中出现两个标签实例。

通过将 UILabel 从 SwiftUI 绑定到 UIViewControllerRepresentable 解决了这个问题,但是当 String 值更新时标签会改变位置。

我不清楚:a)为什么 UIViewControllerRepresentable 会收到两个更新视图的请求,或者 b)为什么 UILabel 会改变位置。

同样,从 SwiftUI 绑定 UILabel 也没有多大意义。这是为了测试嵌入 ViewController 并使用它们来显示标签并不是您真正想要做的,但是为什么会发生这些问题并没有多大意义。

【问题讨论】:

    标签: swift swiftui


    【解决方案1】:

    您可能需要像这样绑定text

     struct DisplayView: UIViewControllerRepresentable  {
     typealias UIViewControllerType = CameraViewController
      @Binding var text: String
     ....
    

    【讨论】:

    • 是的,添加绑定确实有效。但是,遇到了另一个问题,即它会在更改时在旧标签之外创建一个新标签。因此,还必须绑定 UILabel。无论如何,@Binding 是将价值传递到整个链条的关键。
    猜你喜欢
    • 2020-04-05
    • 1970-01-01
    • 1970-01-01
    • 2020-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-28
    • 2022-06-23
    相关资源
    最近更新 更多