如何在 SwiftUI 的视图控制器中实现数据绑定?

How do I implement data binding in a View Controller in SwiftUI?

我有一个 UIKit ViewController,它使用 ViewControllerRepresentable 嵌套在 SwiftUI 视图中。 SwiftUI 视图管理我想在 UIKit 视图中显示的一些状态(在本例中为 Int)。当用户点击 SwiftUI 父视图中的按钮时,状态更改应反映在 UIKit 视图中。我已经尝试使用 @Binding 属性 包装器使两者保持同步,但显然我遗漏了一些东西,因为我的视图控制器的初始化程序会引发编译时错误。

我对 iOS 开发还很陌生,所以我可能走错了方向。任何帮助将不胜感激。

代码如下(简化):

struct ContentView: View {
    @State private var currentNumber: Int

    init(currentNumber: Int) {
        self.currentNumber = currentNumber
    }

    var body: some View {
        FancyLabelViewControllerRepresentable(currentNumber: self.$currentNumber)
        Button("Increment") {
            self.currentNumber += 1
        }
    }
}

struct FancyLabelViewControllerRepresentable: UIViewControllerRepresentable {
    typealias UIViewControllerType = FancyLabelViewController

    @Binding var currentNumber: Int

    init(currentNumber: Binding<Int>) {
        self._currentNumber = currentNumber
    }

    func makeUIViewController(context: Context) -> FancyLabelViewController {
        let fancyLabel = FancyLabelViewController(number: self.currentNumber)
        fancyLabel.currentNumberInLabel = self.currentNumber
        return fancyLabel
    }

    func updateUIViewController(_ uiViewController: FancyLabelViewController, context: Context) {
        uiViewController.currentNumberInLabel = self.currentNumber
    }

}

class FancyLabelViewController: UIViewController {
    var label = UILabel()
    @Binding var currentNumberInLabel: Int

    init(number: Int) {
        // Error: 'self' used in property access 'currentNumberInLabel' before 'super.init' call
        self.currentNumberInLabel = number
        // Error: Property 'self.currentNumberInLabel' not initialized at super.init call
        super.init(nibName: nil, bundle: nil)
    }

    required init(coder: NSCoder) {
        fatalError("Not implemented")
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        label.text = "\(currentNumberInLabel)"
        view = label
    }
}

我认为你不需要

@Binding var currentNumberInLabel: Int

因为 UIViewControllerRepresentable 已经负责更新 currentNumberInLabel 值,但您还需要更新

label.text = "\(currentNumberInLabel)"

所以我做了类似

的事情
class FancyLabelViewController: UIViewController {
    var label = UILabel()
    var currentNumberInLabel: Int

    init(number: Int) {
        self.currentNumberInLabel = number
        super.init(nibName: nil, bundle: nil)
    }

    required init(coder: NSCoder) {
        fatalError("Not implemented")
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        label.text = "\(currentNumberInLabel)"
        view = label
    }
  
    func updateLabel() {
      label.text = "\(currentNumberInLabel)"
    }
}

并从 UIViewControllerRepresentable 调用 updateLabel 作为

func updateUIViewController(_ uiViewController: FancyLabelViewController, context: Context) {
    uiViewController.currentNumberInLabel = self.currentNumber
    uiViewController.updateLabel()
}