RealmSwift查询API返回的是`Query<Date>`而不是`Date`。

huangapple go评论85阅读模式
英文:

RealmSwift query API gives Query<Date> instead of Date

问题

我正在使用RealmSwift来查询特定日期的约会,所以方法看起来像这样:

func appointments(on date: Date) -> [Appointment] {
    realm.objects(Appointment.self)
        .filter {
            Calendar.current.isDate($0.date, inSameDayAs: date)
        }
        .map { $0 }
}

但存在两个问题:

  1. 无法将类型为 'Query' 的值转换为预期的参数类型 'Date'。看起来Realm对象的date属性是Query<Date>而不是Date,我该如何从中获取实际的日期?
  2. 无法将类型为 'Bool' 的值转换为闭包结果类型 'Query'。因此,Realm期望一个Query<Bool>而不是Bool,这与我在Realm的网站上关于查询API的阅读不符: https://www.mongodb.com/developer/products/realm/realm-swift-query-api/

可能有什么问题?

谢谢!

英文:

I'm using RealmSwift to query for appointments on a specific day, so the method looks like:

func appointments(on date: Date) -&gt; [Appointment] {
    realm.objects(Appointment.self)
        .where {
            Calendar.current.isDate($0.date, inSameDayAs: date)
        }
        .map { $0 }
}

But there are two issues:

  1. Cannot convert value of type 'Query<Date>' to expected argument type 'Date'. Looks like the date property from Realm object is a Query&lt;Date&gt; instead of Date, how do I get the actual date from it?
  2. Cannot convert value of type 'Bool' to closure result type 'Query<Bool>'. So realm expects a Query&lt;Bool&gt; instead of Bool, which isn't what I read on Realm's website regarding the query API: https://www.mongodb.com/developer/products/realm/realm-swift-query-api/

What could possibly be wrong?

Thanks!

答案1

得分: 1

Realm查询仅支持Swift中正常操作的一部分。请查看此链接以获取支持的操作列表。这是通过使用Query&lt;T&gt;类型来强制执行的 - 它仅声明了Realm支持的操作,如比较运算符、布尔运算、集合中的in等。您不能像普通的T一样传递Query&lt;T&gt;

确定日期是否与另一个日期在同一天不是受支持的操作之一。您可以取而代之的是找到date的开始和结束,并使用比较运算符来检查对象的date是否介于它们之间。

let calendar = Calendar.current
let start = calendar.startOfDay(for: date)
let end = calendar.date(byAdding: DateComponents(day: 1), to: start)
.where { $0.date &gt;= start &amp;&amp; $0.date &lt; end }
英文:

Realm queries only supports a subset of operations you can do in normal Swift. See this for a list of things it supports. This is enforced by using the Query&lt;T&gt; type - it only declares the Realm-supported operations, like comparison operators, boolean operations, in for collections, etc. You can't pass a Query&lt;T&gt; around, as if it were a normal T.

Determining whether a date is in the same day as another date is not one of the supported operations. What you can do instead is find the beginning and end of date, and use comparison operators to check if the object's date is between them.

let calendar = Calendar.current
let start = calendar.startOfDay(for: date)
let end = calendar.date(byAdding: DateComponents(day: 1), to: start)
.where { $0.date &gt;= start &amp;&amp; $.date &lt; end }

答案2

得分: 0

以下是翻译好的部分:

"有@sweeper提供的一个很好的答案。另一个选项是将日期也存储为另一个对象属性的字符串。

因此,Realm对象将如下所示

class ApptClass: Object {
@Persisted var timestamp: Date!
@Persisted var dateString = ""

convenience init(withDate: Date) {
self.init()
self.timeStamp = withDate
//获取日期作为YYYY-MM-DD格式的字符串
self.dateString = convertDateToDateString(d: withDate) //需要创建此函数
}

从那里,您可以直接查询特定日期

let results = realm.objects(ApptClass.self).where { $0.dateString == "2023-08-09" }

编辑:根据@JoakimDanielson的建议

>您还需要确保在日期更改时更新此属性

其中一种选项是使用由timeStamp和dateString变量支持的非托管计算变量来完成。类似于此伪代码

class ApptClass: Object {
@Persisted var timestamp: Date!
@Persisted var dateString = ""
var useThisToSetTheDate: Date {
set {
设置timeStamp和dateString
}
get {
返回timestamp
}
}
}"

英文:

There's an excellent answer by @sweeper. Another option is store the date also as a string as another object property.

So the Realm object would look like this

class ApptClass: Object {
  @Persisted var timestamp: Date!
  @Persisted var dateString = &quot;&quot;

  convenience init(withDate: Date) {
     self.init()
     self.timeStamp = withDate
     //get the date as a YYYY-MM-DD formatted string
     self.dateString = convertDateToDateString(d: withDate) //need to create this func
}

from there you can then do direct queries for specific dates

let results = realm.objects(ApptClass.self).where { $0.dateString == &quot;2023-08-09&quot; }

Edit: Per a note from @JoakimDanielson

> And you also need to make sure you update this property if the date
> changes

which, and one option, could be accomplished by using an unmanaged computed var that's backed by the timeStamp an dateString var. Something like this pseudo code

class ApptClass: Object {
      @Persisted var timestamp: Date!
      @Persisted var dateString = &quot;&quot;
      var useThisToSetTheDate: Date {
         set {
            set the timeStamp and the dateString
         }
         get {
            return timestamp
         }

huangapple
  • 本文由 发表于 2023年8月9日 16:45:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/76866020-2.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定