I have an app with four (4) views, on the first view I'm showing a list of cars pulled from CoreData, the second view is presented when a car is tapped and it shows the services for each car. The third view is presented when tapping on a service, and it shows the details of the selected service. The fourth view is presented when tapping a button and it shows records for the specified service.
The issue I'm having is that for some reason if I use an @AppStorage property wrapper within the ServicesView I cannot dismiss the fourth view (RecordsView). I don't think the issue is with CoreData but let me know if you need to see the code for Core Data.
Any idea why adding an @AppStorage property wrapper in the ServicesView would affect other views?
CarsView
struct CarsView: View {
@ObservedObject var carViewModel:CarViewModel
@State private var carInfoIsPresented = false
var body: some View {
NavigationView{
VStack{
List {
ForEach(carViewModel.cars) { car in
HStack{
VStack(alignment:.leading){
Text(car.model ?? "")
.font(.title2)
Text(car.make ?? "")
.foregroundColor(Color(UIColor.systemGray))
}
NavigationLink(destination: ServicesView(carViewModel: carViewModel, selectedCar: car)){
Spacer()
Text("Services")
.frame(width: 55)
.font(.caption)
.foregroundColor(Color.systemGray)
}
}
}
}
.listStyle(GroupedListStyle())
.navigationBarTitle("Cars")
.accentColor(.white)
.padding(.top, 20)
}
}
}
}
ServicesView
struct ServicesView: View {
@ObservedObject var carViewModel: CarViewModel
var selectedCar: Car
// ISSUE: No issues dismissing the RecordsView if I comment this out
@AppStorage("sortByNameKey") private var sortByName = true
@State private var selectedService: CarService?
var body: some View {
VStack{
List {
ForEach(carViewModel.carServices) { service in
HStack{
Text(service.name ?? "")
.font(.title3)
NavigationLink(destination: ServiceInfoView(carViewModel: carViewModel, selectedCar: selectedCar, selectedService: service)){
Spacer()
Text("Details")
.font(.caption)
.foregroundColor(Color.systemGray)
}
}
}
}
.navigationBarTitle(Text("\(selectedCar.model ?? "Services") - Services"))
.listStyle(GroupedListStyle())
}
.onAppear{
carViewModel.getServices(forCar: selectedCar)
}
}
}
ServiceInfoView
struct ServiceInfoView: View {
@ObservedObject var carViewModel: CarViewModel
@State private var recordsViewIsPresented = false
@State var selectedCar: Car
@State var selectedService: CarService
var body: some View {
VStack{
Text(selectedService.name ?? "")
.font(.largeTitle)
.padding(.bottom)
VStack{
Button(action: openRecordsView) {
Text("Service History")
}
.padding(10)
.background(Color.blue)
.foregroundColor(Color.white)
.cornerRadius(15)
}
}
.sheet(isPresented: $recordsViewIsPresented){
RecordsView(carViewModel: carViewModel, selectedService: selectedService)
}
}
func openRecordsView(){
recordsViewIsPresented.toggle()
}
}
RecordsView
struct RecordsView: View {
@ObservedObject var carViewModel: CarViewModel
@State var selectedService: CarService
@Environment(\.presentationMode) var presentationMode
var body: some View {
NavigationView {
VStack{
List {
Section(header: Text("Records")) {
ForEach(carViewModel.serviceRecords) { record in
HStack{
Text("Service Date:")
Text("\(record.serviceDate ?? Date(), style: .date)")
.foregroundColor(Color(UIColor.systemGray))
}
}
}
}
.background(Color.purple)
.listStyle(GroupedListStyle())
}
.navigationBarTitle("Records for \(selectedService.name ?? "")", displayMode: .inline)
.navigationBarItems(leading: Button("Cancel", action: dismissView))
.onAppear{
carViewModel.getRecords(forService: selectedService)
}
}
}
func dismissView(){
presentationMode.wrappedValue.dismiss()
}
}
CodePudding user response:
NavigationView
can only push one detail screen unless you set .isDetailLink(false)
on the NavigationLink
.
FYI we don't use view model objects in SwiftUI, you have to learn to use the View struct correctly along with @State
, @Binding
, @FetchRequest
etc. that make the safe and efficient struct behave like an object. If you ignore this and use an object you'll experience the bugs that Swift with its value types was designed to prevent. For more info see this answer MVVM has no place in SwiftUI.