RealmSwift 中记录的不同日期计数?

问题描述 投票:0回答:1

我有带有日期字段的记录:

class SomeRealmObject: Object {
    @Persisted(primaryKey: true) var _id: ObjectId
    @Persisted var date: Date
    ... //some other properties
}

目标是计算按日期不同的记录计数(“不同”应忽略日期内的时间)。

如果我已经有了一个记录列表,我可以像通常的数组元素一样使用它们:

let allObjects = getAll() //SomeRealmObject array
let dates = allObjects.map { $0.startOfDay() }.reduce([]) { partialResult, date in
                partialResult.contains(date) ?
                partialResult : partialResult + [date]
}
let result = dates.count

但是是否可以对

RealmSwift
方法执行相同的操作,因为我只需要计算
SomeRealmObject
而不需要获取其内部数据?例如,有
distinct(by:)
,但它按字段的值进行比较,并且不允许指定其他条件,例如
startOfDay()

swift realm distinct distinct-values realm-mobile-platform
1个回答
0
投票

有几个问题需要克服 - 首先是 Realm 函数不允许我们“挖掘”日期 - 日期是整个日期,包括时间。

因此,使用 Realm 语法无法忽略时间。例如你不能这样做

let distinctObjects = realm.objects(SomeObject.self).distinct {by: "someDate.yyyymmdd"}

无赖。

另一个非工作的想法是使用谓词(Realm 支持一些谓词)和块来隔离日期组件

let myPredicate = NSPredicate(block: { (evaluatedDate, _) -> Bool in
    //isoloate the yyyy mm dd components for evaluation
})

可惜,Realm“仅支持复合、比较和常量谓词”

(许多)解决方案之一是考虑存储的内容 - Date() 对象实际上是一个非常具体的时间戳,其中包括时间。但这不是您的

distinct
所需要的 - 它需要年、月和日

因此,将要比较的日期组件存储为单独的属性;可能是字符串或没有时间成分的日期

class SomeRealmObject: Object {
    @Persisted(primaryKey: true) var _id: ObjectId
    @Persisted var date: Date
    @Persisted var dateString = "" //stored as yyyymmdd
    //or
    @Persisted var dateNoTime: Date //stored as a date with 0's as time
}

可以通过提取要区分的日期组件来构建

dateNoTime
属性,创建一个新的日期对象并存储它;例如

let components = DateComponents(year: 2023, month: 04, day: 01)
let theDate = Calendar.current.date(from: components)

从那里有很多路径,一种是使用 Realm 属性支持的函数或计算属性来处理日期,因此在对象上设置日期时,它会写出实际的时间戳版本以及使用的时间戳版本为了独特。

class SomeRealmObject: Object {
    @Persisted(primaryKey: true) var _id: ObjectId
    @Persisted var date: Date
    @Persisted var dateString = "" //stored as yyyymmdd

    func writeDate(withDate: Date) {
       self.date = withDate
       self.dateString = //break down withDate to yyyymmdd
    }
}

然后你可以使用 Realms

distinct
来获取结果

let distictObjects = realm.objects(SomeObject.self).distict(by: ["dateString"]

*注意,这也可以通过将对象加载到数组中并然后使用 Swift 谓词进行评估来完成,但这可能会导致内存问题并且可能会更慢。

© www.soinside.com 2019 - 2024. All rights reserved.