Home > Net >  How can I create a button in SwiftUI to reload both a random value, both the displayed items?
How can I create a button in SwiftUI to reload both a random value, both the displayed items?

Time:12-20

I have the following view:

//
//  RandomMinifig.swift
//  MinifiguresV4
//
//  Created by Nicolò Campagnoli on 19/12/22.
//

import SwiftUI

struct RandomMinifig: View {
    let minifigs: [Minifig] = Bundle.main.decode("minifigures.json")
    
   
    var body: some View {
        var random = Int.random(in: 1...minifigs.count)
        let minifig = minifigs[random]
        
        
        NavigationView {
            VStack {
                Image("Series\(minifig.id)")
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .frame(width: 250, height: 250)
                
                Text("\(minifig.name)")
                    .font(.headline)
                Text("\(minifig.series) • \(minifig.number)")
                Text("\(String(format: "%.2f", minifig.price))€")
                    .foregroundColor(.gray)
            }
            .navigationTitle("Random minifigure")
            
        }
    } 
}

struct RandomMinifig_Previews: PreviewProvider {
    static var previews: some View {
        RandomMinifig()
    }
}

That creates a simple view with a random object with an image in the middle on the screen

I tried to add a button or a text with the option .onTapGesture, and also added a .refreshable option in the navigation view, both re-givining a value to 'random'. but this option didn't reload the full page. My goal was a simple button to press, that generates an other random number, that displays an other object

CodePudding user response:

Hi you must use @State property wrapper the UI/Model combined changes. Here there's your file corrected(I've also changed the Json decode process to the right one.

import SwiftUI

struct RandomMinifig: View {

let minifigs: [Minifig] = {
    guard let filePath = Bundle.main.path(forResource: "data", ofType: "json") else {print("file path") ; return []}
    guard let fileContent = try? String(contentsOfFile: filePath).data(using: .utf8) else {print("file content") ;return []}
    guard let minifigs = try? JSONDecoder().decode([Minifig].self, from: fileContent) else {print("decode problem") ;return []}
    return minifigs
}()

var random: Int {
    guard minifigs.count > 0 else {return 0}
    return Int.random(in: 0...minifigs.count - 1) // If the json file is empty throw an error because it tries to take a number in an invalid range(0 ... - 1)
}
@State var currentMinifig: Minifig = Minifig(id: "", name: "", series: "", number: 0, price: 0)


var body: some View {
    
    
    NavigationView {
        VStack {
            Image("Series\(currentMinifig.id)")
                .resizable()
                .aspectRatio(contentMode: .fit)
                .frame(width: 250, height: 250)
            
            Text("\(currentMinifig.name)")
                .font(.headline)
            Text("\(currentMinifig.series) • \(currentMinifig.number)")
            Text("\(String(format: "%.2f", currentMinifig.price))€")
                .foregroundColor(.gray)
            Button("Reload") {
                currentMinifig = minifigs[random]
            }
        }
        .navigationTitle("Random minifigure")
        .onAppear {
            guard minifigs.count > 0 else {currentMinifig = Minifig(id: "", name: "", series: "", number: 0, price: 0); return}
            currentMinifig = minifigs[random]
        }
        
    }
}
}



struct Minifig: Codable {
var id: String
var name: String
var series: String
var number: Int
var price: Double
}

Sorry for the bad indentation but I don't understand so well how Stack Overflows works.

Here there the json files that I used as model

[
{
"name" : "ted",
"id" : "1",
"series" : "0",
"number" : 0,
"price" : 10
},
{
"name" : "steve",
"id" : "2",
"series" : "0",
"number" : 2,
"price" : 20
}
]
  • Related