Tailwind CSSTailwind CSS
Home
  • Tailwind CSS 书籍目录
  • Vue 3 开发实战指南
  • React 和 Next.js 学习
  • TypeScript
  • React开发框架书籍大纲
  • Shadcn学习大纲
  • Swift 编程语言:从入门到进阶
  • SwiftUI 学习指南
  • 函数式编程大纲
  • Swift 异步编程语言
  • Swift 协议化编程
  • SwiftUI MVVM 开发模式
  • SwiftUI 图表开发书籍
  • SwiftData
  • ArkTS编程语言:从入门到精通
  • 仓颉编程语言:从入门到精通
  • 鸿蒙手机客户端开发实战
  • WPF书籍
  • C#开发书籍
learn
  • Java编程语言
  • Kotlin 编程入门与实战
  • /python/outline.html
  • AI Agent
  • MCP (Model Context Protocol) 应用指南
  • 深度学习
  • 深度学习
  • 强化学习: 理论与实践
  • 扩散模型书籍
  • Agentic AI for Everyone
langchain
Home
  • Tailwind CSS 书籍目录
  • Vue 3 开发实战指南
  • React 和 Next.js 学习
  • TypeScript
  • React开发框架书籍大纲
  • Shadcn学习大纲
  • Swift 编程语言:从入门到进阶
  • SwiftUI 学习指南
  • 函数式编程大纲
  • Swift 异步编程语言
  • Swift 协议化编程
  • SwiftUI MVVM 开发模式
  • SwiftUI 图表开发书籍
  • SwiftData
  • ArkTS编程语言:从入门到精通
  • 仓颉编程语言:从入门到精通
  • 鸿蒙手机客户端开发实战
  • WPF书籍
  • C#开发书籍
learn
  • Java编程语言
  • Kotlin 编程入门与实战
  • /python/outline.html
  • AI Agent
  • MCP (Model Context Protocol) 应用指南
  • 深度学习
  • 深度学习
  • 强化学习: 理论与实践
  • 扩散模型书籍
  • Agentic AI for Everyone
langchain

读取对象

在 SwiftData 中,你可以通过多种方式读取数据,以满足不同的查询需求。本节将详细介绍两种主要的读取方式:声明式查询 (@Query 宏) 和命令式查询 (ModelContext.fetch()),以及如何使用谓词、排序描述符、数量限制和偏移量来精确控制查询结果。

使用 @Query 宏进行声明式查询

@Query 是 SwiftData 提供的一个强大的属性包装器,它允许你在 SwiftUI 视图中以声明式的方式定义数据查询。当 underlying 数据发生变化时,@Query 会自动更新视图,使得 UI 始终保持与数据同步。

import SwiftUI
import SwiftData

struct ContentView: View {
    // 声明式查询,获取所有 Task 对象
    @Query var tasks: [Task]

    var body: some View {
        List {
            ForEach(tasks) { task in
                Text(task.name)
            }
        }
    }
}

带有谓词的 @Query

你可以通过传入 Predicate 参数来过滤查询结果。例如,我们只想显示已完成的任务:

import SwiftUI
import SwiftData

struct ContentView: View {
    // 查询所有已完成的任务
    @Query(filter: #Predicate<Task> { $0.isCompleted == true }) var completedTasks: [Task]

    var body: some View {
        List {
            ForEach(completedTasks) { task in
                Text(task.name)
            }
        }
    }
}

带有排序描述符的 @Query

你还可以通过 sort 参数来指定查询结果的排序方式。例如,按任务创建日期降序排列:

import SwiftUI
import SwiftData

struct ContentView: View {
    // 按创建日期降序查询所有任务
    @Query(sort: \Task.creationDate, order: .reverse) var tasks: [Task]

    var body: some View {
        List {
            ForEach(tasks) { task in
                Text(task.name)
            }
        }
    }
}

你也可以提供多个排序描述符,SwiftData 会按照它们在数组中的顺序进行排序。

使用 ModelContext.fetch() 进行命令式查询

除了声明式查询,SwiftData 还提供了命令式查询方式,即通过 ModelContext 的 fetch() 方法来执行更复杂的、一次性的或非视图驱动的数据检索。这在你需要在业务逻辑层或不直接与 SwiftUI 视图交互的地方获取数据时非常有用。

fetch() 方法需要一个 FetchDescriptor 对象作为参数,该对象封装了查询的所有细节。

import SwiftData

func fetchTasks(context: ModelContext) throws {
    // 创建一个 FetchDescriptor,指定要查询的类型
    let descriptor = FetchDescriptor<Task>()

    do {
        let allTasks = try context.fetch(descriptor)
        print("所有任务: \(allTasks.count) 个")
    } catch {
        print("获取任务失败: \(error)")
    }
}

谓词 (Predicate) 的使用:#Predicate

谓词是过滤查询结果的关键。SwiftData 利用 Swift 5.9 引入的 #Predicate 宏,以一种类型安全和可读性强的方式定义复杂的查询条件。

// 查询所有名称包含 "SwiftData" 且未完成的任务
let predicate = #Predicate<Task> { task in
    task.name.contains("SwiftData") && task.isCompleted == false
}

var descriptor = FetchDescriptor<Task>(predicate: predicate)
let filteredTasks = try context.fetch(descriptor)

#Predicate 宏的强大之处在于,它能在编译时进行类型检查,并能被 SwiftData 运行时转换为高效的数据库查询语言(例如 SQL)。

你可以使用各种比较运算符 (==, !=, >, <, >=, <=)、逻辑运算符 (&&, ||, !) 以及字符串方法 (contains, starts(with:), ends(with:)) 来构建复杂的谓词。

排序 (Sort Descriptors)

通过 FetchDescriptor 的 sortBy 属性,你可以添加一个或多个 SortDescriptor 来指定结果的排序方式。

// 按创建日期升序,然后按名称降序排列
var descriptor = FetchDescriptor<Task>()
descriptor.sortBy = [
    SortDescriptor(\.creationDate, order: .forward),
    SortDescriptor(\.name, order: .reverse)
]
let sortedTasks = try context.fetch(descriptor)

限制数量与偏移 (Limit & Offset)

当你只需要部分数据或实现分页功能时,可以使用 FetchDescriptor 的 fetchLimit 和 fetchOffset 属性。

  • fetchLimit: 限制返回结果的数量。
  • fetchOffset: 跳过指定数量的结果,从偏移量之后开始返回。
// 查询前 5 个任务,跳过最开始的 10 个任务
var descriptor = FetchDescriptor<Task>()
descriptor.fetchLimit = 5
descriptor.fetchOffset = 10
let paginatedTasks = try context.fetch(descriptor)

结合 fetchLimit 和 fetchOffset,你可以轻松实现分页加载功能,提高应用性能和用户体验。


通过本节的学习,你已经掌握了 SwiftData 中读取对象的多种方法,包括声明式的 @Query 和命令式的 ModelContext.fetch()。同时,你也了解了如何利用谓词、排序描述符、限制数量和偏移量来精确控制你的数据查询。在实际开发中,根据你的需求选择最合适的查询方式,将能更高效地管理和展示你的应用数据。

你现在对 SwiftData 的数据读取操作有更清晰的认识了吗?或者你希望了解如何在更复杂的场景下应用这些查询技巧?

Last Updated:: 5/30/25, 7:06 PM