SwiftUI 预览中的 PreviewProvider 中的 State 不起作用

huangapple go评论54阅读模式
英文:

SwiftUI State in Preview with PreviewProvider is not working

问题

我有一个简单的按钮,在模拟器上按预期工作,形状会随点击而变;

```swift
结构体 ButtonTest: View {
    @State var isLiked = true
    var body: some View {

        VStack {
            LikeButtonSimple( action: toggleLiked, isLiked: $isLiked)
        }
    }
    func toggleLiked() {
    
        isLiked.toggle()
        print("Liked Button: \(isLiked)")
    }
}

结构体 LikeButtonSimple: View {
    
    let dimen = 50.0
    let dimenHalf = CGFloat(28)
    
    var action: () -> Void?
    
    @Binding var isLiked : Bool

    var body: some View {
        ZStack {
            Circle()
                .frame(width: dimen, height: dimen)
                .foregroundColor(.white )
                .shadow(color: .black, radius: 2, y: 2)
            Button( action: {
               action()
            }
            ) {
                Image(systemName: isLiked ? "heart.fill" : "heart")
                    .resizable()
                    .foregroundColor(isLiked ? .red : .gray)
                    .frame(width: dimenHalf, height: dimenHalf)
            }
        }
    }
}

我想在 Preview 上看到相同的行为,为此编写了以下内容;

结构体 LikeButtonSimple_Previews: PreviewProvider {

    @State static var isLiked = true

    static func toggleLiked() {

        isLiked.toggle()
    }

    static var previews: some View {
        LikeButtonSimple( action: toggleLiked, isLiked: $isLiked)

    }
}

按钮不再切换。我们能在 Preview 中使用这个 PreviewProvider 来解决吗?


<details>
<summary>英文:</summary>

I&#39;ve a simple button that work on simulator as expected, the shape changes with click;

```swift
struct ButtonTest: View {
    @State var isLiked = true
    var body: some View {

        VStack {
            LikeButtonSimple( action: toggleLiked, isLiked: $isLiked)
        }
    }
    func toggleLiked() {
    
        isLiked.toggle()
        print(&quot;Liked Button: \(isLiked)&quot;)
    }
}

struct LikeButtonSimple: View {
    
    let dimen = 50.0
    let dimenHalf = CGFloat(28)
    
    var action: () -&gt; Void?
    
    @Binding var isLiked : Bool

    var body: some View {
        ZStack {
            Circle()
                .frame(width: dimen, height: dimen)
                .foregroundColor(.white )
                .shadow(color: .black, radius: 2, y: 2)
            Button( action: {
               action()
            }
            ) {
                Image(systemName: isLiked ? &quot;heart.fill&quot; : &quot;heart&quot;)
                    .resizable()
                    .foregroundColor(isLiked ? .red : .gray)
                    .frame(width: dimenHalf, height: dimenHalf)
            }
        }
    }
}

I want to see the same behavior on the Preview as well and wrote the below for it;

struct LikeButtonSimple_Previews: PreviewProvider {

    @State static var isLiked = true

    static func toggleLiked() {

        isLiked.toggle()
    }

    static var previews: some View {
        LikeButtonSimple( action: toggleLiked, isLiked: $isLiked)

    }
}

The button doesn't toggle anymore. Can we work this on Preview with this PreviewProvider?

答案1

得分: 2

由于Xcode的“预览”是静态的,无法保存变量的更改值。

要在“预览”中更改值,您将需要使用其中包含状态值的容器视图。

struct LikeButtonSimple_Previews: PreviewProvider {
    
    //包装实际视图并保存状态变量的视图。
    struct ContainerView: View {
        @State private var isLiked = true
        
        var body: some View {
            LikeButtonSimple(action: toggleLiked, isLiked: $isLiked)
        }
        
        func toggleLiked() {
            isLiked.toggle()
        }
    }

    static var previews: some View {
        ContainerView()
    }
}
英文:

As Xcode Preview is static, it can't hold changed value of variable.

To change value in Preview, you will have to use the container view inside it which will holds the state value.

struct LikeButtonSimple_Previews: PreviewProvider {
    
    //A view which will wraps the actual view and holds state variable. 
    struct ContainerView: View {
        @State private var isLiked = true
        
        var body: some View {
            LikeButtonSimple(action: toggleLiked, isLiked: $isLiked)
        }
        
        func toggleLiked() {
            isLiked.toggle()
        }
    }

    static var previews: some View {
        ContainerView()
    }
} 

答案2

得分: 1

我认为在这里根本不需要操作。

绑定是与某些数据的双向连接。

通过使用绑定,您传递给它的视图可以对其进行更新。

因此,您不需要绑定和操作。按钮操作应该只是…

isLiked.toggle()

这就足以更新视图并在“父”视图中更新该值。

英文:

I think you don’t need the action here at all.

A binding is a two way connection to some data.

By using a binding the view that you pass it to can make updates to it.

So you do not need the bonding and the action. The button action should just do…

isLiked.toggle()

This is enough for the view to update and for the value to be updated in the “parent” view.

huangapple
  • 本文由 发表于 2023年4月6日 22:46:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/75950856.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定