RealmSwift display for each date to tableview section

僤鯓⒐⒋嵵緔 提交于 2019-12-18 07:17:11

问题


I'm new in swift and realm.

I want to display data which are stored in realm.

I want to display for each date to tableview section.

Item Object
class Item: Object {
    @objc dynamic var amount: Int = 0
    @objc dynamic var date: Date?
    var parentCategory = LinkingObjects(fromType: Category.self, property: "items")
}

viewController

import UIKit
import RealmSwift

class HistoryViewController: UITableViewController {

    let realm = try! Realm()
    var items: Results<Item>?

    override func viewDidLoad() {
        super.viewDidLoad()
        items = realm.objects(Item.self)
    }


    override func numberOfSections(in tableView: UITableView) -> Int {
        return items?.count ?? 1
    }

    override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return "represents a day"
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return "Item entries with the corresponding date"
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
        cell.textLabel?.text = amount
        return cell
    }

}
date stored
Optional(Results<Item> <0x7ff9ba460610> (
[0] Item {
    amount = 900;
    date = 2018-01-27 06:00:06 +0000;
},
[1] Item {
    amount = 9000;
    date = 2018-01-27 06:20:29 +0000;
},
[2] Item {
    amount = 400;
    date = 2018-01-28 06:22:32 +0000;
},
[3] Item {
    amount = 45;
    date = 2018-01-28 01:21:27 +0000;
},
[4] Item {
    amount = 258665;
    date = 2018-01-30 02:35:45 +0000;
}

))

I want to display like below
  • 2018-01-27
    • 900
    • 9000
  • 2018-01-28
    • 400
    • 45
  • 2018-01-30
    • 258665

回答1:


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
    }

}


来源:https://stackoverflow.com/questions/48621128/realmswift-display-for-each-date-to-tableview-section

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!