Highlight
SwiftData 是 Apple 为 Swift 推出的原生数据持久化框架,用
@Model宏直接在 Swift 代码中定义数据模型,自动与 SwiftUI 集成,开发者无需编写 Core Data 的繁琐样板代码即可获得完整的增删改查和 iCloud 同步能力。
核心内容
以前要在 iOS 上做数据持久化,Core Data 几乎是唯一选择。但它的学习曲线陡峭:你需要理解 .xcdatamodeld 文件、NSManagedObject、NSPredicate、NSFetchRequest 这些概念,还要在 Swift 和 Objective-C 的 API 之间来回切换。一个简单的查询可能要写十几行代码,而且类型不安全,编译期无法检查错误。
WWDC23 推出的 SwiftData 改变了这个局面。
SwiftData 完全基于 Swift 代码,没有外部文件格式。你写一个普通的 Swift class,加上 @Model 宏,它就自动具备了持久化能力。字符串、整数、日期这些值类型直接变成数据属性,其他模型类的引用自动变成关系属性。不需要 .xcdatamodeld 文件,不需要生成代码,Schema 就是你的 Swift 代码本身。
查询也变得更简单。SwiftData 引入了原生的 Predicate 和 FetchDescriptor,完全替代了 NSPredicate。你可以在 Xcode 里获得自动补全,编译器会检查类型错误。一个查询从原来的十几行缩减到两三行。
和 SwiftUI 的集成是开箱即用的。在 App 的 scene 上加一个 .modelContainer() modifier,在 View 里用 @Query 和 @Environment(\.modelContext),数据就能自动绑定到 UI 上。修改模型属性,界面自动刷新;插入或删除数据,列表自动更新。
SwiftData 还内置了 CloudKit 同步、Undo/Redo、Widget 支持等平台能力。这些以前需要大量额外工作才能实现的功能,现在几乎是免费的。
数据建模
(01:09)SwiftData 的核心是 @Model 宏。把它加在一个 class 上,SwiftData 就会自动分析这个类的存储属性,生成对应的持久化 Schema。
import SwiftData
@Model
class Trip {
var name: String
var destination: String
var endDate: Date
var startDate: Date
var bucketList: [BucketListItem]? = []
var livingAccommodation: LivingAccommodation?
}
关键点:
@Model只能用于 class,因为模型需要引用语义- 值类型属性(String、Int、Date、struct、enum、Codable)自动成为 attributes
- 其他模型类的引用自动成为 relationships
- 集合类型(数组)也支持
(02:46)你可以用 @Attribute 和 @Relationship 添加元数据:
@Model
class Trip {
@Attribute(.unique) var name: String
var destination: String
var endDate: Date
var startDate: Date
@Relationship(.cascade) var bucketList: [BucketListItem]? = []
var livingAccommodation: LivingAccommodation?
}
关键点:
@Attribute(.unique)给 name 添加唯一性约束@Relationship(.cascade)表示删除 Trip 时,关联的 bucketList 项也会被级联删除- 用
@Transient可以标记不参与持久化的属性
容器与上下文
(03:43)ModelContainer 是持久化后端,ModelContext 是操作数据的接口。
初始化容器有两种方式:
// 默认配置
let container = try ModelContainer([Trip.self, LivingAccommodation.self])
// 自定义配置
let container = try ModelContainer(
for: [Trip.self, LivingAccommodation.self],
configurations: ModelConfiguration(url: URL("path"))
)
在 SwiftUI 中,用 modifier 设置容器:
import SwiftUI
@main
struct TripsApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
.modelContainer(
for: [Trip.self, LivingAccommodation.self]
)
}
}
关键点:
.modelContainer()会自动把容器注入到 SwiftUI 环境中- 可以配置 URL、CloudKit 容器标识符、迁移选项等
- SwiftUI 还会自动传播 modelContext
(04:20)在 View 中获取上下文:
import SwiftUI
struct ContextView: View {
@Environment(\.modelContext) private var context
}
查询数据
(05:13)SwiftData 使用原生的 Predicate 宏构建查询条件,替代了 NSPredicate:
let today = Date()
let tripPredicate = #Predicate<Trip> {
$0.destination == "New York" &&
$0.name.contains("birthday") &&
$0.startDate > today
}
关键点:
#Predicate是 Swift 宏,支持强类型检查- Xcode 提供自动补全
- 条件表达式使用原生 Swift 语法
(05:32)用 FetchDescriptor 执行查询:
let descriptor = FetchDescriptor<Trip>(predicate: tripPredicate)
let trips = try context.fetch(descriptor)
(05:46)添加排序:
let descriptor = FetchDescriptor<Trip>(
sortBy: SortDescriptor(\.Trip.name),
predicate: tripPredicate
)
let trips = try context.fetch(descriptor)
关键点:
FetchDescriptor支持 predicate、sort、预取关系、结果限制等多种选项SortDescriptor支持原生 Swift 类型和 keypath
修改数据
(06:15)ModelContext 提供了完整的增删改接口:
var myTrip = Trip(name: "Birthday Trip", destination: "New York")
// 插入新对象
context.insert(myTrip)
// 删除对象
context.delete(myTrip)
// 保存变更
try context.save()
关键点:
- 创建模型对象和普通 Swift class 一样
insert()后对象开始被上下文跟踪- 属性修改会自动被跟踪,下次 save 时提交
- 支持 undo/redo
SwiftUI 集成
(07:38)@Query 属性包装器让数据绑定变得极其简单:
import SwiftUI
struct ContentView: View {
@Query(sort: \.startDate, order: .reverse) var trips: [Trip]
@Environment(\.modelContext) var modelContext
var body: some View {
NavigationStack() {
List {
ForEach(trips) { trip in
// ...
}
}
}
}
}
关键点:
@Query自动从上下文中获取数据- 支持排序和过滤
- 数据变化时 SwiftUI 自动刷新视图
- SwiftData 支持新的 Observable 特性,属性变化自动触发 UI 更新
详细内容
从 Core Data 迁移
SwiftData 和 Core Data 可以共存。Apple 提供了从 Core Data 迁移到 SwiftData 的指南,包括:
- 共享同一个持久化存储文件
- 逐步迁移模型
- 保持 CloudKit 同步
相关文档:Adopting SwiftData for a Core Data app
FetchDescriptor 的高级用法
FetchDescriptor 除了 predicate 和 sort,还支持:
- 预取关系对象,减少数据库往返
- 限制结果数量
- 排除未保存的变更
- 自定义获取属性
这些选项让你可以精确控制查询行为,优化性能。
平台集成
SwiftData 与多个 Apple 平台特性无缝协作:
- CloudKit:自动 iCloud 同步,无需额外代码
- Widgets:Widget 可以直接读取 SwiftData 数据
- Undo/Redo:ModelContext 内置支持
- Spotlight:可以集成 Core Spotlight 索引
核心启发
1. 用 SwiftData 重写你的笔记/待办 App
- 做什么:把原来用 UserDefaults 或文件存储的笔记应用迁移到 SwiftData
- 为什么值得做:获得完整的数据查询能力(按日期、标签筛选)、自动 iCloud 同步、Undo 支持
- 怎么开始:给 Note 模型加
@Model,用@Query替换原来的数组,用FetchDescriptor实现搜索和筛选
2. 做一个支持离线缓存的阅读器 App
- 做什么:RSS 阅读器或文章收藏 App,支持离线阅读和同步
- 为什么值得做:SwiftData 的 CloudKit 集成让多设备同步几乎零成本,FetchDescriptor 的预取功能可以优化阅读体验
- 怎么开始:定义 Article 模型,用
@Relationship关联 Tag,用 predicate 实现已读/未读筛选
3. 做一个旅行规划 App(类似 Demo 中的 Trip 应用)
- 做什么:管理旅行计划、行李清单、预算记录
- 为什么值得做:SwiftData 的关系模型天然适合这种多实体关联的场景,SwiftUI 集成让界面开发极快
- 怎么开始:创建 Trip、BucketListItem、LivingAccommodation 等模型,用
@Relationship(.cascade)管理关联删除
4. 给现有 SwiftUI App 添加数据持久化
- 做什么:把原来内存中的状态持久化到本地
- 为什么值得做:只需加
@Model和.modelContainer(),改动极小,收益很大 - 怎么开始:识别需要持久化的数据模型,添加
@Model宏,在 App 入口配置容器
关联 Session
- Model your schema with SwiftData — 深入了解 SwiftData 的数据建模细节,包括复杂关系和迁移策略
- Dive deeper into SwiftData — SwiftData 容器配置、上下文管理和高级查询技巧
- Build an app with SwiftData — 从零开始用 SwiftData 构建完整应用
- SwiftUI — SwiftUI 基础和新特性
评论
GitHub Issues · utterances