SwiftData在视图中使用动态属性进行查询

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

SwiftData query with dynamic properties in a View

问题

我正在尝试找出如何创建一个SwiftUI视图,该视图可以显示来自SwiftData的数据,使用包含传递到视图的变量的查询。我猜想我可能无法使用@Query语法,但是否有人找到了一种可行的方法来做类似这样的事情?

我是否需要放弃@Query,只是创建一个视图模型,该模型实例化自己的ModelContainer和ModelContext?

这段代码显然无法编译,因为@Query引用了startDate和endDate变量,但这正是我想要的。

  1. struct MyView: View {
  2. @Environment(\.modelContext) var modelContext
  3. @Query(FetchDescriptor<Measurement>(predicate: #Predicate<Measurement> {
  4. $0.date >= startDate && $0.date <= endDate }, sortBy: [SortDescriptor(\Measurement.date)])) var measurements: [Measurement]
  5. let startDate: Date = Date.distantPast
  6. let endDate: Date = Date.distantFuture
  7. var body: some View {
  8. Text("Help")
  9. }
  10. }
英文:

I'm trying to figure out how to make a SwiftUI view that displays data from SwiftData using a query that includes variables passed into the view. I'm guessing that I won't be able to use the @Query syntax, but has anyone come up with a workable method to do something like this?

Do I need to abandon the @Query and just create a view model that instantiates it's own ModelContainer and ModelContext?

This code is obviously not compiling because the @Query is referencing the startDate and endDate variables, but this is what I want.

  1. struct MyView: View {
  2. @Environment(\.modelContext) var modelContext
  3. @Query(FetchDescriptor&lt;Measurement&gt;(predicate: #Predicate&lt;Measurement&gt; {
  4. $0.date &gt;= startDate &amp;&amp; $0.date &lt;= endDate }, sortBy: [SortDescriptor(\Measurement.date)])) var measurements: [Measurement]
  5. let startDate: Date = Date.distantPast
  6. let endDate: Date = Date.distantFuture
  7. var body: some View {
  8. Text(&quot;Help&quot;)
  9. }
  10. }

答案1

得分: 2

你不能拥有一个动态查询(还没有),但一个解决方法是将日期(或完整谓词)注入到视图中,然后以这种方式创建查询。

  1. @Query var measurements: [Measurement]
  2. init(startDate: Date, endDate: Date) {
  3. let predicate = #Predicate<Measurement> {
  4. $0.date >= startDate && $0.date <= endDate
  5. }
  6. _measurements = Query(filter: predicate, sort: \.date)
  7. }
英文:

You can't have a dynamic query (not yet) but a workaround is to inject in the dates (or the full predicate) into the view and create the query that way.

  1. @Query var measurements: [Measurement]
  2. init(startDate: Date, endDate: Date) {
  3. let predicate = #Predicate&lt;Measurement&gt; {
  4. $0.date &gt;= startDate &amp;&amp; $0.date &lt;= endDate
  5. }
  6. _measurements = Query(filter: predicate, sort: \.date)
  7. }

答案2

得分: 0

我写了一个内部类来显示列表中的筛选记录:

  1. struct DemoListContentView: View {
  2. @Environment(\.modelContext) private var modelContext
  3. @Query(
  4. FetchDescriptor()
  5. ) private var items: [Item]
  6. init(endDate: Date) {
  7. let past = Date.distantPast
  8. let predicate = #Predicate<Item> {
  9. ($0.creationDate ?? past) <= endDate
  10. }
  11. _items = Query(filter: predicate)
  12. }
  13. var body: some View {
  14. NavigationView {
  15. VStack{
  16. Text("\(items.count)")
  17. List {
  18. ForEach(items) { item in
  19. ItemCell(item: item)
  20. }
  21. }
  22. }
  23. }
  24. }
  25. }

它将在以下地方调用:

  1. import SwiftUI
  2. import SwiftData
  3. struct ContentView: View {
  4. @Environment(\.modelContext) private var modelContext
  5. @State var lastFetch = Date()
  6. var body: some View {
  7. DemoListContentView(endDate: lastFetch)
  8. }
  9. }

希望能有所帮助。

英文:

my two cents. I wrote an inner class to show filtered record in list:

  1. struct DemoListContentView: View {
  2. @Environment(\.modelContext) private var modelContext
  3. @Query(
  4. FetchDescriptor()
  5. ) private var items: [Item]
  6. init(endDate: Date) {
  7. let past = Date.distantPast
  8. let predicate = #Predicate&lt;Item&gt; {
  9. ($0.creationDate ?? past) &lt;= endDate
  10. }
  11. _items = Query(filter: predicate)
  12. }
  13. var body: some View {
  14. NavigationView {
  15. VStack{
  16. Text(&quot;\(items.count)&quot;)
  17. List {
  18. ForEach(items) { item in
  19. ItemCell(item: item)
  20. }
  21. }
  22. }
  23. }
  24. }
  25. }

it will called in:

  1. import SwiftUI
  2. import SwiftData
  3. struct ContentView: View {
  4. @Environment(\.modelContext) private var modelContext
  5. @State var lastFetch = Date()
  6. var body: some View {
  7. ListContentView(endDate: lastFetch)
  8. }
  9. }

Hope can help.

huangapple
  • 本文由 发表于 2023年6月22日 03:23:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/76526517.html
匿名

发表评论

匿名网友

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

确定