SwiftUI如何在View在初始化程序中需要@Binding时实例化PreviewProvider

Posted

技术标签:

【中文标题】SwiftUI如何在View在初始化程序中需要@Binding时实例化PreviewProvider【英文标题】:SwiftUI How to instantiate PreviewProvider when View requires @Binding in initializer 【发布时间】:2020-03-01 06:22:00 【问题描述】:

使用 SwiftUI (Xcode 11.1),我设置了一些带有 2 向绑定的视图(使用 @Binding)。双向更新效果很好。

但是,如何从 PreviewProvider 实例化视图?

例如:

struct AddProjectView: View 

    @Binding public var showModal: Bool

    var body: some View 

        return VStack 
            Text("Add Project View")
            Button("Dismiss") 
                self.showModal = false
            
        
    

我不能这样做,因为“true”不是绑定:

struct AddProjectView_Previews: PreviewProvider 
    static var previews: some View 
        AddProjectView(showModal: true)
    

我不能这样做,因为“本地属性尚不支持属性包装器”:

struct AddProjectView_Previews: PreviewProvider 
    static var previews: some View 
        @Binding var show = true
        return AddProjectView(showModal: $show)
    

我们如何做到这一点?

谢谢!!

【问题讨论】:

【参考方案1】:

您必须在预览中将其声明为 @State。

struct AddProjectView_Previews: PreviewProvider 

     @State static var showModal: Bool = false

     static var previews: some View 
         AddProjectView(showModal: $showModal)
     

还要记住它需要是静态的,因为它用于静态函数。

【讨论】:

XCode 11.3 中的行为实际上与使用.constant(false) 相同,即如果您使用实时预览,则无法更改该值。【参考方案2】:

.constant 正是为此而生的:

/// 使用不可变的value 创建一个绑定。

struct AddProjectView: View 
    @Binding public var showModal: Bool
    var body: some View 
        return VStack 
            Text("Add Project View")
            Button("Dismiss") 
                self.showModal = false
            
        
    


struct AddProjectView_Previews: PreviewProvider 
    static var previews: some View 
        AddProjectView(showModal: .constant(true))
    

【讨论】:

【参考方案3】:

如果您只需要一个常量值,请使用.constant(VALUE)

struct YourView_Previews: PreviewProvider 

    static var previews: some View 
        YourView(yourBindingVar: .constant(true))
    


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

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)
        
    


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

【讨论】:

您不知道您的回答如何帮助我生成更好的代码。太感谢了。我仍在学习 SWIFTUI 和您编写的 BindingProvider,这超出了我有限的 swift 知识。我有一种感觉,但不理解 100%。无论如何,谢谢。 老兄这个答案应该是推荐的答案!

以上是关于SwiftUI如何在View在初始化程序中需要@Binding时实例化PreviewProvider的主要内容,如果未能解决你的问题,请参考以下文章

如何创建一个带有可选辅助 View 参数的 SwiftUI 视图?

如何在 swiftUI 中创建一个普通视图

如何在 SwiftUI 中创建一个获取 View 并返回自定义结果的函数?

SwiftUI - 如何在 init 中使用 fetchRequest 更新数据

SwiftUI 移除 NavigationBar 底部边框

是啥导致 SwiftUI 嵌套的 View 项目在初始绘制后出现跳跃动画?