Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.0k views
in Technique[技术] by (71.8m points)

ios - RealmSwift display for each date to tableview section

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
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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
    }

}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...