0

I have a view that makes an API call to pull nearby restaurant data and display it in a list. I've placed a button in the navigation bar of that view to display a sheet which will ultimately show the user filter options. For now, it uses a Picker placed in a form to allow the user to pick how they want to sort the results. I am using a variable with a @Binding property wrapper in the filter view to pass the selected value to a @State variable in the restaurant data view (selectedOption). It all works great until the view is reloaded. Either by going to a different view or relaunching the app. It appears the selectedOption variable in my API call in the onAppear function of the restaurant data view is being reset to what I've set the default value to when I defined the @State variable. I am wondering if there is a way to persist the value of what was chosen in the filter view through view reloads of the restaurant data view.

Restaurant data view:

import SwiftUI
import SwiftyJSON
import SDWebImageSwiftUI

struct RestaurantsView: View {
    
    @EnvironmentObject var locationViewModel: LocationViewModel
    @EnvironmentObject var venueDataViewModel: VenueDataViewModel

    @State var selectedOption: String = "rating"
    @State private var showingSheet = false
    @State private var searchText = ""
    @State private var showCancelButton: Bool = false
    
    var body: some View {
        
        let CPLatitude: Double = locationViewModel.lastSeenLocation?.coordinate.latitude ?? 0.00
        let CPLongitude: Double = locationViewModel.lastSeenLocation?.coordinate.longitude ?? 0.00

        GeometryReader { geometry in
            VStack {
                Text("Restaurants")
                    .padding()
                
                List(venueDataViewModel.venuesListTen) { index in
                    NavigationLink(destination: RestaurantsDetailView(venue: index)) {
                        HStack {
                            VStack(alignment: .leading, spacing: 6) {
                                Text(index.name ?? "")
                                    .font(.body)
                                    .lineLimit(2)
                                Text(index.address ?? "")
                                    .font(.subheadline)
                                    .lineLimit(2)
                            }
                        }
                    }
                    
                    Spacer()
                    if index.image != nil {
                        WebImage(url: URL(string: index.image ?? ""), options: .highPriority, context: nil)
                            .resizable()
                            .frame(width: 70, height: 70, alignment: .center)
                            .aspectRatio(contentMode: .fill)
                            .cornerRadius(12)
                    }
                }
                
                Text("Selected: \(selectedOption)")
                
                Spacer()
            }.toolbar {
                ToolbarItem(placement: .navigationBarLeading) {
                    Button(action: {
                            showingSheet.toggle()
                    }, label: {
                        Image(systemName: "line.horizontal.3")
                            .imageScale(.large)
                    }
                    )
                .sheet(isPresented: $showingSheet, content: {
                            NavigationView {
                                RestaurantsFilterView(selectedOption: self.$selectedOption)
                            }
                })
                }
            }
            .onAppear {
                venueDataViewModel.retrieveVenues(latitude: CPLatitude, longitude: CPLongitude, category: "restaurants", limit: 50, sortBy: selectedOption, locale: "en_US") { (response, error) in
                    if let error = error {
                        print("\(error)")
                    }
                }
            }
        }
    }
}

Filter view:

import SwiftUI

struct RestaurantsFilterView: View {
    
    @EnvironmentObject var locationViewModel: LocationViewModel
    @EnvironmentObject var venueDataViewModel: VenueDataViewModel
    
    var sortOptions = ["rating", "review_count"]
    
    @Binding var selectedOption: String
    
    var body: some View {
        
        let CPLatitude: Double = locationViewModel.lastSeenLocation?.coordinate.latitude ?? 0.00
        let CPLongitude: Double = locationViewModel.lastSeenLocation?.coordinate.longitude ?? 0.00
        
        VStack {
            Text("Filter")
            Form {
                Section {
                    Picker(selection: $selectedOption, label: Text("Sort")) {
                        ForEach(sortOptions, id: \.self) {
                            Text($0)
                        }
                    }.onChange(of: selectedOption) { Equatable in
                        venueDataViewModel.retrieveVenues(latitude: CPLatitude, longitude: CPLongitude, category: "restaurants", limit: 50, sortBy: selectedOption, locale: "en_US") { (response, error) in
                            if let error = error {
                                print("\(error)")
                            }
                        }
                    }
                }
            }
        }
    }
}

I am still new to Swift and SwiftUI so I appreciate the help. Thank you!

bmmcc4
  • 45
  • 5
  • This really is data you want to persist. You should use UserDefaults for it. See [How can I use UserDefaults in Swift?](https://stackoverflow.com/questions/31203241/how-can-i-use-userdefaults-in-swift) – Yrb Jul 30 '21 at 19:07
  • @Yrb Thank you! I was able to get it setup using UserDefaults and it works great! – bmmcc4 Jul 30 '21 at 22:25

0 Answers0