Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI Reload View

Tags:

swiftui

I have a struct which shuffles and Lists records from CoreData. I would like to reload / Refresh the List view with a Button. I tried to use a function from within the Button. Is there a way I can do this?

    var body: some View {


            VStack {

                       List {

                           ForEach(dictionary.shuffled().prefix(upTo: 10),id: \.self) { word in


                            HStack {
                               Text("\(word.englishWord)")
                                    .foregroundColor(Color.blue)

                                Text("| \(word.urhoboWord) |")
                                    .foregroundColor(Color.green)

                                Image(word.imageName)
                                    .resizable()
                                    .frame(width:40, height: 40)


                            }//HStack

                           }//End of ForEach

                        }//End of List

                //Button to reload and shuffle list
                Button(action: {}) {

                    Text("Shuffle")
                        .padding()
                        .background(Color.black)
                        .foregroundColor(Color.white)
                        .cornerRadius(6)
                }


                        .navigationBarTitle(Text("Begin Learning"),displayMode: .inline)


like image 233
ufookoro Avatar asked Jan 23 '20 06:01

ufookoro


3 Answers

You should move this dictionary.shuffled().prefix(upTo: 10) to your ViewModel and your view just reload base on the data. Take a look at this code for reference:

struct SampleShuffleView : View {
    @ObservedObject var viewModel : ShuffleViewModel = ShuffleViewModel()

    var body : some View {
        VStack {
            List(self.viewModel.listData, id: \.self) { str in
                Text(str)
            }

            Button(action: self.shuffle) {
                Text("Shuffle me").padding()
            }.background(Color.white).padding()

        }
    }

    func shuffle() {
        self.viewModel.shuffle()
    }
}

class ShuffleViewModel : ObservableObject {
    @Published var listData = ["one", "two", "three", "four"]

    func shuffle() {
        listData.shuffle()
        //or listData = dictionary.shuffled().prefix(upTo: 10)
    }
}

Note: All view's components will be reloaded when @ObservedObject changes, so consider to separate smaller view-viewmodel(s), or using @State variable.

Hope this helps.

like image 58
Quang Hà Avatar answered Nov 12 '22 03:11

Quang Hà


Just trigger any value of the @State or @Published of @ObservableObject. If you do not have such, just create one:

@State var refresh: Bool = false

func update() {
   refresh.toggle()
}
like image 30
Neph Muw Avatar answered Nov 12 '22 05:11

Neph Muw


Think about. To show array and shuffle on tap, do exactly what you would like to see. first show us the array in some "list" like manner and next shuffle it on user action.

struct ContentView: View {
    @State var arr = ["ALFA", "BETA", "GAMA", "DELTA"]
    var body: some View {
        VStack {
        VStack {
            Divider()
            ForEach(arr, id: \.self) { element in
                VStack {
                    Text(element)
                    Divider()
                }
            }
        }
            Spacer()
            Button(action: {
                self.arr.shuffle()
            }) {
                Text("Shuffle")
            }
            Spacer()
        }
    }
}

arr.shuffle() changed the @State of View and force SwiftUI to "reload it" automatically.

like image 32
user3441734 Avatar answered Nov 12 '22 04:11

user3441734