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

Posted

技术标签:

【中文标题】如何在 SwiftUI 的视图控制器中实现数据绑定?【英文标题】:How do I implement data binding in a View Controller in SwiftUI? 【发布时间】:2021-09-22 13:17:13 【问题描述】:

我有一个 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
    


【问题讨论】:

【参考方案1】:

我认为你不需要

@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()

【讨论】:

以上是关于如何在 SwiftUI 的视图控制器中实现数据绑定?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 SwiftUI 中实现 MVVM 模式?视图不会重新渲染

如何在 SwiftUI 中的 WatchOS 中实现 handleUserActivity?

如何在batmanjs中实现导航菜单

SwiftUI - 如何在 SwiftUI 中弹出到特定视图?

如何在 SwiftUI 中实现触发 switch case 的左或右 DragGesture()?

SwiftUI 中如何获取任意视图触摸位置(全局或局部)的坐标