I’m attempting to build a todo app using SwiftUI + Swift Data. I’ve created a model like this:
@Model
final class toDoItem: Identifiable {
var title: String = ""
var emoji: String = ""
var notes: String = ""
var toDoColor: String = ""
var toDoLocation: String = ""
var timeStamp: Date = Date.now
var isCompleted: Bool = false
var isCritical: Bool = false
var isOverdue: Bool = false
//Saving the image somewhere else and loading only the reference in the Model
@Attribute(.externalStorage)
var image: Data?
//Creating a relationship between a category and a todo.
@Relationship(deleteRule:.nullify, inverse: Category.items)
var category: Category?
//initializing all vars
init(title: String = "", emoji: String = "", notes: String = "", toDoColor: String = "", toDoLocation: String = "", timeStamp: Date = .now, isCompleted: Bool = false, isCritical: Bool = false, isOverdue: Bool = false) {
self.title = title
self.emoji = emoji
self.notes = notes
self.toDoColor = toDoColor
self.toDoLocation = toDoLocation
self.timeStamp = timeStamp
self.isCompleted = isCompleted
self.isCritical = isCritical
self.isOverdue = isOverdue
}
}
I want to create a list to display all the todos with a section for each item’s timeStamp.
For example, if I have four todos with two of them having Sep 19th 2024 as the timeStamp and the other two having Sep 21st 2024, I want a list with two sections: one with Sep 19th 2024 as the header with the relative two todo items, and another one with Sep 21st 2024 containing the other two todo items.
I also have a search bar and need to filter the todos according to the user’s search. This is the code for my list view:
struct MainView: View {
@Environment(.modelContext) var context
@Query private var items: [toDoItem]
@State private var searchQuery = ""
@State private var selectedSortOptions = SortOptions.allCases.first!
var filteredItems: [toDoItem] {
if searchQuery.isEmpty{
return items.sort(on: selectedSortOptions)
}
let filteredItems = items.compactMap{ item in
//Search for content in todo Title
let titleContainsQuery = item.title.range(of: searchQuery, options: .caseInsensitive) != nil
//Search for content in todo Emoji
let emojiContainsQuery = item.emoji.range(of: searchQuery, options: .caseInsensitive) != nil
//Search for content in todo Category Title
let categoryContainsQuery = item.category?.catTitle.range(of: searchQuery, options: .caseInsensitive) != nil
return (titleContainsQuery || categoryContainsQuery || emojiContainsQuery) ? item : nil
}
return filteredItems.sort(on: selectedSortOptions)
}
//MAIN VIEW Content
var body: some View {
NavigationStack{
List{
ForEach(filteredItems) { item in
ForEach(item.timeStamp) { day in
Section{
...
}
}
}
}
}
}
}
I’m having an issue with the second ForEach loop, which contains a filter for each timeStamp. I’m getting the error “Generic struct ‘ForEach’ requires that ‘Date’ conform to ‘RandomAccessCollection'”. What am I doing wrong? I’m fairly new to coding and SwiftUI and I feel like I’m overlooking something. Thank you.