0

We can change the image with the help of a button using state variable as Boolean. But how do we achieve that using a string variable?

For Example:

If State variable is a bool:-

Image(systemName: self.typeClicked ? "heart.fill" : "heart.fill")

what will come in the place of " self.typeClicked ? "heart.fill" : "heart.fill" " if the state variable is String?

When the typeClicked = "success" the image should change, if it is other than "success" the image should retain its previous condition.

What I have tried so far:

State variables:

    @State private var type: String = "success"
    
    @State private var typeClicked: Bool =  false
    
    @StateObject var viewModel = addWishlist()

MyView :

  VStack{
            HStack {
                Image("resort1")
                Spacer()
                Button {
                    if viewModel.responses?.type == "success" {
                        typeClicked.toggle()
                    } else {
                        typeClicked = false
                    }
                } label: {
                    Image(systemName: self.typeClicked ? "heart.fill" : "heart.fill")
                        .font(.system(size: 25))
                        .foregroundColor(self.typeClicked ? .red : Color.init(uiColor: .systemGray3))
                }
            }
            .padding()
        }

Network class:

class addWishlist: ObservableObject {

@Published private(set) var records: addRecord?

@Published private(set) var responses: add?

func loadData() {
    let url = URL(string: addwishlist_URL)
    guard let requestUrl = url else { fatalError() }
    
    var request = URLRequest(url: requestUrl)
    request.httpMethod = "POST"
    
    let postString = "roomid=xxxxxxxxxxx&emailid=xxxxxxxxxxxx"
    
    request.httpBody = postString.data(using: String.Encoding.utf8);
    
    let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
        do {
            if let todoData = data {
                let decodedData = try JSONDecoder().decode(add.self, from: todoData)
                DispatchQueue.main.async {
                    self.records = decodedData.record
                    print(decodedData.record)
                    print(decodedData.type)
                }
            } else {
                print("No data")
            }
        } catch {
            print(error)
        }
    }
    task.resume()
}

}

structs:

struct add: Codable { var type: String let record: addRecord }

I want my view to be changed only with "type". which is "type": "success" in my api response.

1
  • Unrelated, but why is responses optional? Commented Mar 1, 2023 at 9:09

1 Answer 1

0

try this approach, when you want to have typeClicked a String:

 @State private var type: String = "success"
 @State private var typeClicked = "fail"  // <-- here
 @StateObject var viewModel = addWishlist()
 
  //.....
 
     VStack{
         HStack {
             Image("resort1")
             Spacer()
             Button {
                 if viewModel.responses?.type == "success" {
                     // toggle equivalent
                     typeClicked = typeClicked == "success" ? "fail" : "success"  // <-- here
                 } else {
                     typeClicked = "fail"   // <-- here
                 }
             } label: {
                 Image(systemName: typeClicked == "success" ? "heart.fill" : "heart")  // <-- here
                     .font(.system(size: 25))
                     .foregroundColor(typeClicked == "success" ? .red : Color.init(uiColor: .systemGray3))  // <-- here
             }
         }
         .padding()
     }

Note, you could also just use Image(systemName: "heart.fill") and just play with the filling color, .foregroundColor(typeClicked == "success" ? .red : Color.init(uiColor: .systemGray3))

EDIT-1:

Here is my fully working code I used to test my answer. When you tap/click on the heart button, it changes color depending on the typeClicked String value.

struct ContentView: View {
    @State private var type: String = "success"
    @State private var typeClicked = "fail"  // <-- here
  // @StateObject var viewModel = addWishlist()  // commented for testing
    
    var body: some View {
        VStack{
            HStack {
                Image("resort1")
                Spacer()
                Button {
                    // simulated toggle, like you had it with the Bool
                    typeClicked = typeClicked == "success" ? "fail" : "success"
                    // commented for testing
//                    if viewModel.responses?.type == "success" {
                          // typeClicked = "success"   // <-- alternative to toggle
//                        typeClicked = typeClicked == "success" ? "fail" : "success"
//                    } else {
//                        typeClicked = "fail"
//                    }
                } label: {
                    Image(systemName: "heart.fill")
                        .font(.system(size: 25))
                        .foregroundColor(typeClicked == "success" ? .red : Color.init(uiColor: .systemGray3))
                }
            }
            .padding()
        }
    }
}
Sign up to request clarification or add additional context in comments.

12 Comments

thanks for your response, Already tried this method but the image colour remains gray. That isn't changing!? any other possible way?
updated my answer to have the color changing. When you click on the Button the heart will change color.
Your EDIT-1 working fine, but that's not working with the condition [/ if viewModel.responses?.type == "success" { // typeClicked = "success" // <-- alternative to toggle // typeClicked = typeClicked == "success" ? "fail" : "success" // } else { // typeClicked = "fail" // }]
what exactly do you want to happen when viewModel.responses?.type == "success". Do you want the heart to be red or gray? Note, my code address your question ...We can change the image with the help of a button using state variable as Boolean. But how do we achieve that using a string variable?. My answer does that.
Well, great, the "type" is nil, and my code does exactly what you want to do, the heart stay gray, because viewModel.responses?.type is not equal to "success". Note that in your loadData() you do not set responses to anything, that is why it is alway nil. You should use the convention of naming your types in uppercase, such as struct Add: Codable .... and give them more meaningful names.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.