swiftuipreviewswiftui-buttonswiftui-state

SwiftUI State in Preview with PreviewProvider is not working


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?


Solution

  • 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()
        }
    }