IOS Realm groups by date in tableView section

I have a realm database that contains data and the date this data was added. I want to exctract this and set the date as the heading of the table section and the data, since the row data for each section depends on the date. I know how to exctract, but I don’t know how to group by date and set the data for each section depending on the date. Thanks!

+4
source share
4 answers

You can use CoreData as an alternative to Realm and use the selected result controller, which allows you to sort data and group some variables.

-8
source

Results , , / .

class Person {
    dynamic var name = ""
    dynamic var date = NSDate()
}

let sortedObjects = realm.objects(Person).sorted("date")

var lastDate = objects.first?.date
let calendar = NSCalendar.currentCalendar()
var lastGroup = [Person]()
var groups = [[Person]]()

for element in sortedObjects {
    let currentDate = element.date
    let difference = calendar.components([.Year, .Month, .Day], fromDate: lastDate!, toDate: currentDate, options: [])
    if difference.year > 0 || difference.month > 0 || difference.day > 0 {
        lastDate = currentDate
        groups.append(lastGroup)
        lastGroup = [element]
    } else {
        lastGroup.append(element)
    }
}
groups.append(lastGroup)

.. , . , , , Results.

+3

, Realm , , .

, :

final class Appointment: Object {
    @objc dynamic var id: Int = 0
    @objc dynamic var date: Date?
}

, /, :

// (un)safely get an instance of Realm
let realm = try! Realm()

// get all the dates
// note that begginingOfDay is a extension on Date
// which gives back the beggining of the day of the given Date as a Date
// we are doing this in order to filter out non-unique dates later
let dates = self.realm.objects(Appointment.self).toArray().flatMap({ $0.date ?? nil }).map({ $0.beginningOfDay() })

// cast it to a Set to make values unique, and back to an Array for further use
let uniqueDates = Array(Set(dates))

let predicates = uniqueDates.map({ date -> NSPredicate in

    // in order to use Swift Date with NSPredicate
    // it must be casted to NSDate
    let begginingOfDay = date.beginningOfDay() as NSDate
    let endOfDay = date.endOfDay() as NSDate

    // create a predicate that checks if the given Date is in between
    // the beggining of a given Date and the end of the given Date
    let predicate = NSPredicate(format: "(date >= %@) AND (date <= %@)", begginingOfDay, endOfDay)

    return predicate
})

// create an array of Results<Appointment>, and then use it to drive your table/collection view
// I will leave this part to you, depends on your UI implementation
// personally, I wrap this into another object that contains results, section index, section title, etc.
// and then I use all of that in my table view data source methods          
let sectionedResults: [Results<Appointment>] = predicates.map({ predicate -> Results<Appointment> in
    let results = realm.objects(Appointment.self).filter(predicate)
    return results
})

, , .

+1

If someone fights with Swift 3.0 syntax:

    var lastDate = dateObjects.first?.start
    let calendar = Calendar.current
    var lastGroup = [DateObject]()
    var days = [[DateObject]]()

    for dateObject in dateObjects {
        let currentDate = dateObject.start
        let unitFlags : Set<Calendar.Component> = [.era, .day, .month, .year, .timeZone]
        let difference = calendar.dateComponents(unitFlags, from: lastDate!, to: currentDate)

        if difference.year! > 0 || difference.month! > 0 || difference.day! > 0 {
            lastDate = currentDate
            days.append(lastGroup)
            lastGroup = [travelTime]
        } else {
            lastGroup.append(dateObject)
        }
    }
    days.append(lastGroup)
0
source

Source: https://habr.com/ru/post/1609178/


All Articles