0

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

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

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

struct 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)
            }
        }
    }
}

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?

kelalaka
  • 5,064
  • 5
  • 27
  • 44

2 Answers2

2

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()
    }
} 
Hardik Shekhat
  • 1,680
  • 12
  • 21
  • Yes, It seems the [one of the ways](https://stackoverflow.com/a/66175501/1820553). Even more, a constant can be provided so that isLiked doesn't need to have initial value. – kelalaka Apr 07 '23 at 06:12
  • You can't get the updated value when you will use `.constant(true)` instead of `State` var. – Hardik Shekhat Apr 07 '23 at 06:32
  • 1
    `ContainerView(isLiked = true)`is working, I've tested and removed the initialization of isLiked – kelalaka Apr 07 '23 at 06:59
  • Yes, that way also you can initialise the isLiked value. – Hardik Shekhat Apr 07 '23 at 08:32
  • 1
    @kelalaka this is exactly what I meant in the last comment on my answer. I’m on my phone and couldn’t update though. This is not coding style. This is how to easily make a preview. – Fogmeister Apr 07 '23 at 09:28
1

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.

Fogmeister
  • 76,236
  • 42
  • 207
  • 306
  • Well, it was part of some design consideration. Even, I can remove the action and call toggle inside of the button's action, the PreviewProvider doesn't behave correctly. So there is something else about this... – kelalaka Apr 06 '23 at 15:18
  • Can you not use the container view. The ButtonTest view in the preview provider. That way it already has the binding baked into it – Fogmeister Apr 06 '23 at 15:56
  • Sorry, I did not get it. Could you elaborate it? This is running normally in the app, I just want to create a preview. – kelalaka Apr 06 '23 at 18:46
  • But the preview could just be a view that contains the button rather than making the preview just the button itself. – Fogmeister Apr 06 '23 at 21:00
  • I think you are talking how to code in some style, all I want to ability of preview the design updates on preview even after integration of the view.. – kelalaka Apr 07 '23 at 07:01
  • Yes, you are right about that I don't need to toggle with a function, I was testing capabilites... – kelalaka Apr 09 '23 at 08:45