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

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

RealmSwift query API gives Query<Date> instead of Date

问题

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

func appointments(on date: Date) -> [Appointment] {
    realm.objects(Appointment.self)
        .filter("date == %@", 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).filter("dateString == %@", "2023-08-09")

编辑:根据@JoakimDanielson的注释:

如果日期发生变化,您还需要确保更新此属性

可以通过使用一个由timeStamp和dateString变量支持的非托管计算属性来实现。类似于以下伪代码:

class ApptClass: Object {
      @Persisted var timestamp: Date!
      @Persisted var dateString = ""
      var useThisToSetTheDate: Date {
         set {
            设置timeStamp和dateString
         }
         get {
            return 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.html
匿名

发表评论

匿名网友

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

确定