【问题标题】:Mutable Binding in SwiftUI Live PreviewSwiftUI 实时预览中的可变绑定
【发布时间】:2019-12-09 10:27:13
【问题描述】:

我有一个带有变量的 ChildView:

@Binding var itemName: String

在这个 ChildView 中,我有几个按钮可以更改变量的值:

Button(action: {
    self.itemName = "different value"
})

我试图像这样使用预览:

struct ChildView_Previews: PreviewProvider {
    static var previews: some View {
        ChildView(itemName: "test")
    }
}

但我收到一个错误:

无法将“字符串”类型的值转换为预期的参数类型 '绑定'

我知道我可以使用如下所示的预览。并且错误将消失并且预览将起作用,但是... itemName 将具有恒定值,它现在不会是可变的,在实时预览中不是交互式的:

struct ChildView_Previews: PreviewProvider {
    static var previews: some View {
        ChildView(itemName: .constant("test"))
    }
}

如何在 SwiftUI Preview 中声明绑定以使其具有交互性?

【问题讨论】:

    标签: swift xcode swiftui


    【解决方案1】:

    更新PreviewProvider 中的@State 变量似乎不会直接更新只读计算属性previews。解决方案是将@State 变量包装在测试持有者视图中。然后在previews 属性中使用此测试视图,以便实时预览正确刷新。在 Xcode 11.2.1 中测试和工作。

    struct ChildView: View {
        @Binding var itemName: String
    
        var body: some View {
            VStack {
                Text("Name: \(itemName)")
                Button(action: {
                    self.itemName = "different value"
                }) {
                    Text("Change")
                }
            }
        }
    }
    
    struct ChildView_Previews: PreviewProvider {
    
        struct BindingTestHolder: View {
            @State var testItem: String = "Initial"
            var body: some View {
                ChildView(itemName: $testItem)
            }
        }
    
        static var previews: some View {
            BindingTestHolder()
        }
    }
    

    【讨论】:

    • 谢谢,Asperi,但它不起作用。没有错误,但 Live Preview 中的 itemName 仍然不是交互式的。我想是因为@Binding var itemName: String。我还更新了我的问题以显示我如何使用按钮来更改 itemName 的值。
    • 我相信它以前有效......现在看起来@State 不再使previews 无效。已更新。
    【解决方案2】:

    如果您需要一个可以在实时预览中更改的值,我喜欢使用这个帮助类:

    struct BindingProvider<StateT, Content: View>: View {
    
        @State private var state: StateT
        private var content: (_ binding: Binding<StateT>) -> Content
    
        init(_ initialState: StateT, @ViewBuilder content: @escaping (_ binding: Binding<StateT>) -> Content) {
            self.content = content
            self._state = State(initialValue: initialState)
        }
    
        var body: some View {
            self.content($state)
        }
    }
    

    像这样使用它:

    struct YourView_Previews: PreviewProvider {
    
        static var previews: some View {
            BindingProvider(false) { binding in
                YourView(yourBindingVar: binding)
            }
        }
    
    }
    

    这允许您在实时预览中测试更改绑定。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-05-23
      • 1970-01-01
      • 2021-01-13
      • 2020-06-11
      • 2020-07-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多