Conditionally showing List or other views

This...is...nuts.

Logically, I understand why it doesn't work. If this was ObjC, I'd probably have it worked out by now. But in SwiftUI, I'm stumped.

Here's my code:

struct CalendarView: View {
    
    @StateObject var selectedDate = SelectedDate()
    
    @Environment(\.managedObjectContext) private var viewContext
    
    @FetchRequest(
        sortDescriptors: [NSSortDescriptor(keyPath: \Expense.eName, ascending: true)],
        animation: .default)
    private var expenses: FetchedResults<Expense>
    
    var body: some View {
        VStack {
            
            CalendarHelper(interval: DateInterval(start: .distantPast, end: .distantFuture), date: selectedDate)
            
            ForEach(expenses, id:\.self) { exp in
                
                if selectedDate.selectedDate.isInSameDay(as: exp.eDueDate ?? Date()) {
                    List {
                        ExpenseRowItemView(eName: exp.eName ?? "",
                                           eCategory:  exp.eCategoryName ?? "",
                                           eDueDate: exp.eDueDate ?? Date(),
                                           eImageName: exp.eCategoryName ?? "",
                                           showEdit: false)
                    }
                }
            }
            
            VStack {
                GeometryReader { geometry in
                    Image("emptyView")
                        .resizable()
                        .aspectRatio(contentMode: .fit)
                        .frame(width: geometry.size.width, height: geometry.size.height)
                }
                Text ("No Data")
                Spacer()
            }
        }
    }
}

For the sake of argument, lets just say that I've got a UICalendarView connected to Core Data. Its pulling in and marking events on the calendar correctly. When I select a date with a corresponding decoration, the list item shows correctly under the calendar.

Because of the way I'm showing this list, when an item is not selected it should show the Image and Text. And...when the view first loads it does. Obviously, when an item on the calendar is selected and it has a corresponding event, the image is pushed down and the Calendar, list item and empty image/text is shown.

I've tried adding a bool to only show the image/text when the selected date doesnt match the event date, but because of views and my lack of understanding of MVVM, its not working.

Thanks for your help.

Answered by capitalF in 751009022

So I worked out a solution. Its kind of kludgy but it works. I'd appreciate any comments or alternative solutions.

struct CalendarView: View {
    
    @StateObject var selectedDate = SelectedDate()
    
    @Environment(\.managedObjectContext) private var viewContext
    
    @FetchRequest(
        sortDescriptors: [NSSortDescriptor(keyPath: \Expense.eName, ascending: true)],
        animation: .default)
    private var expenses: FetchedResults<Expense>
    
    @State private var listIsVisible:Bool = false
    
    var body: some View {
        VStack {
            
            CalendarHelper(interval: DateInterval(start: .distantPast, end: .distantFuture), date: selectedDate)
            
            ForEach(expenses, id:\.self) { exp in
                
                if selectedDate.selectedDate.isInSameDay(as: exp.eDueDate ?? Date()) {
                    List {
                        ExpenseRowItemView(eName: exp.eName ?? "",
                                           eCategory:  exp.eCategoryName ?? "",
                                           eDueDate: exp.eDueDate ?? Date(),
                                           eImageName: exp.eCategoryName ?? "",
                                           showEdit: false)
                    }.onAppear(){listIsVisible = true}
                } else {
                    Text("")
                        .hidden()
                        .onAppear(){listIsVisible = false}
                }
            }
            
            if !listIsVisible {
                VStack {
                    GeometryReader { geometry in
                        Image("emptyView")
                            .resizable()
                            .aspectRatio(contentMode: .fit)
                            .frame(width: geometry.size.width, height: geometry.size.height)
                    }
                    Text ("No Data")
                        .onAppear(){listIsVisible = false}
                    Spacer()
                }
            }
        }
    }
}

Thanks!

Accepted Answer

So I worked out a solution. Its kind of kludgy but it works. I'd appreciate any comments or alternative solutions.

struct CalendarView: View {
    
    @StateObject var selectedDate = SelectedDate()
    
    @Environment(\.managedObjectContext) private var viewContext
    
    @FetchRequest(
        sortDescriptors: [NSSortDescriptor(keyPath: \Expense.eName, ascending: true)],
        animation: .default)
    private var expenses: FetchedResults<Expense>
    
    @State private var listIsVisible:Bool = false
    
    var body: some View {
        VStack {
            
            CalendarHelper(interval: DateInterval(start: .distantPast, end: .distantFuture), date: selectedDate)
            
            ForEach(expenses, id:\.self) { exp in
                
                if selectedDate.selectedDate.isInSameDay(as: exp.eDueDate ?? Date()) {
                    List {
                        ExpenseRowItemView(eName: exp.eName ?? "",
                                           eCategory:  exp.eCategoryName ?? "",
                                           eDueDate: exp.eDueDate ?? Date(),
                                           eImageName: exp.eCategoryName ?? "",
                                           showEdit: false)
                    }.onAppear(){listIsVisible = true}
                } else {
                    Text("")
                        .hidden()
                        .onAppear(){listIsVisible = false}
                }
            }
            
            if !listIsVisible {
                VStack {
                    GeometryReader { geometry in
                        Image("emptyView")
                            .resizable()
                            .aspectRatio(contentMode: .fit)
                            .frame(width: geometry.size.width, height: geometry.size.height)
                    }
                    Text ("No Data")
                        .onAppear(){listIsVisible = false}
                    Spacer()
                }
            }
        }
    }
}

Thanks!

Conditionally showing List or other views
 
 
Q