You have to make quite a few changes in order to group your tableview based on days to which the date
property of Item
corresponds.
First of all, you shouldn't store all items as a property of your class, since you won't be needing all items in one collection. Rather, the approach I suggest is to use an Array and a Dictionary as the data sources for your table view. The array will store the unique days (the Date
objects in the array will correspond to midnight of the specific day) for which you have entries in Realm
. The dictionary will contain the same days as its keys and the values will be of type Results<Item>
for storing each Item
whose date
property is on the same day as the specific key.
I have tested below code in a playground and its working as expected.
class HistoryViewController: UITableViewController {
let realm = try! Realm()
var groupedItems = [Date:Results<Item>]()
var itemDates = [Date]()
override func viewDidLoad() {
super.viewDidLoad()
let items = realm.objects(Item.self)
//Find each unique day for which an Item exists in your Realm
itemDates = items.reduce(into: [Date](), { results, currentItem in
let date = currentItem.date!
let beginningOfDay = Calendar.current.date(from: DateComponents(year: Calendar.current.component(.year, from: date), month: Calendar.current.component(.month, from: date), day: Calendar.current.component(.day, from: date), hour: 0, minute: 0, second: 0))!
let endOfDay = Calendar.current.date(from: DateComponents(year: Calendar.current.component(.year, from: date), month: Calendar.current.component(.month, from: date), day: Calendar.current.component(.day, from: date), hour: 23, minute: 59, second: 59))!
//Only add the date if it doesn't exist in the array yet
if !results.contains(where: { addedDate->Bool in
return addedDate >= beginningOfDay && addedDate <= endOfDay
}) {
results.append(beginningOfDay)
}
})
//Filter each Item in realm based on their date property and assign the results to the dictionary
groupedItems = itemDates.reduce(into: [Date:Results<Item>](), { results, date in
let beginningOfDay = Calendar.current.date(from: DateComponents(year: Calendar.current.component(.year, from: date), month: Calendar.current.component(.month, from: date), day: Calendar.current.component(.day, from: date), hour: 0, minute: 0, second: 0))!
let endOfDay = Calendar.current.date(from: DateComponents(year: Calendar.current.component(.year, from: date), month: Calendar.current.component(.month, from: date), day: Calendar.current.component(.day, from: date), hour: 23, minute: 59, second: 59))!
results[beginningOfDay] = realm.objects(Item.self).filter("date >= %@ AND date <= %@", beginningOfDay, endOfDay)
})
}
override func numberOfSections(in tableView: UITableView) -> Int {
return itemDates.count
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return "represents a day"
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return groupedItems[itemDates[section]]!.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
let itemsForDate = groupedItems[itemDates[indexPath.section]]!
cell.textLabel?.text = "(Array(itemsForDate.sorted(byKeyPath: "date"))[indexPath.row].amount)"
return cell
}
}