【问题标题】:iOS Realm grouping by date to tableView sectionsiOS Realm 按日期分组到 tableView 部分
【发布时间】:2015-09-27 12:48:46
【问题描述】:

我有领域数据库,其中包含数据和添加此数据的日期。我想提取它并将日期设置为表格视图部分标题,并将数据设置为每个部分的行数据取决于日期。我知道如何提取但不知道如何按日期分组并为每个部分设置数据取决于日期。谢谢!

【问题讨论】:

    标签: ios objective-c realm


    【解决方案1】:

    Swift 4 使用高阶函数而非循环实现。

    class Item: Object {
      @objc dynamic var id: Int = 0
      @objc dynamic var date: Date = Date()
    }
    
    let realm = try! Realm()
    
    // fetch all Items sorted by date
    let results = realm.objects(Item.self).sorted(byKeyPath: "date", ascending: false)              
    
    let sections = results
        .map { item in
            // get start of a day
            return Calendar.current.startOfDay(for: item.date)
        }
        .reduce([]) { dates, date in
            // unique sorted array of dates
            return dates.last == date ? dates : dates + [date]
        }
        .compactMap { startDate -> (date: Date, items: Results<Item>) in
            // create the end of current day
            let endDate = Calendar.current.date(byAdding: .day, value: 1, to: startDate)!
            // filter sorted results by a predicate matching current day
            let items = results.filter("(date >= %@) AND (date < %@)", startDate, endDate)
            // return a section only if current day is non-empty
            return items.isEmpty ? nil : (date: startDate, items: items)
        }
    

    【讨论】:

      【解决方案2】:

      您可以按日期对检索到的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's 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's data source methods          
        let sectionedResults: [Results<Appointment>] = predicates.map({ predicate -> Results<Appointment> in
            let results = realm.objects(Appointment.self).filter(predicate)
            return results
        })
        

        你现在应该对如何做有一个大概的了解,我将把 UI 实现的细节留给你。

        【讨论】:

          【解决方案4】:

          如果有人在使用 Swift 3.0 语法:

              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)
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2012-06-27
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-09-28
            • 1970-01-01
            • 2019-04-02
            • 1970-01-01
            相关资源
            最近更新 更多