写点什么

SwiftData 迎来大升级:查询能力增强,支持第三方类型持久化

作者:Sergio De Simone
  • 2026-07-17
    北京
  • 本文字数:1500 字

    阅读完需:约 5 分钟

SwiftData 在 2027 版本中新增了通过 Codable 持久化自定义类型和第三方类型的支持,同时加入了将数据组织到 SwiftUI 列表分区中的能力。此外,它还通过 ResultsObserver 和 HistoryObserver 增加了观察数据存储变化的新能力。

Codable 属性解决了 SwiftData 在集成自定义类型或第三方类型时存在的一项限制。由于开发者无法控制第三方引用类型,因此无法为其添加 @Model 标记。这样一来,该类型就无法直接包含到模型中,因为 SwiftData 无法为其生成 Schema。

不过,在新版本中,只要第三方类型遵循 Codable 协议,就可以无缝与 SwiftData 配合使用。下面的示例中,ExLocation 是一个我们无法控制的值类型,它可能来自 iOS SDK,也可能来自第三方库:

struct ExLocation: Codable {    ...}@Modelfinal class Destination {    var title: String    @Attribute(.codable) var locationInfo: ExLocation        init(title: String, locationInfo: ExLocation) {        self.title = title        self.locationInfo = locationInfo    }}
复制代码

在 SwiftData 模型中使用 Codable 属性也存在一些限制。最明显的一点是,这类属性无法用于过滤或排序,因为它们会被视为不透明值。此外,底层类型发生变化时,例如新增一个属性,并不会触发自动迁移。由于这些限制,对于开发者自己控制的类型,使用 .codable 并不被认为是一种好的实践。在这些情况下,目前更实用的方式仍然是将它们定义为 @Model 类型。

为了支持分区查询,SwiftData 扩展了 @Query 属性包装器,新增 sectionBy 参数,允许开发者指定查询类型中的 KeyPath,用于数据分组:

@Query(sort: \Trip.startDate, sectionBy: \.destination)var trips: [Trip]
复制代码

传入 sectionBy 参数后,被包装的对象 _trips 会暴露一个 sections 属性,开发者可以通过该属性遍历各个分区:

List {    ForEach (_trips.sections) { section in         Section(section.id) {            ForEach(section) { trip in                TripListItem(trip: trip)            }        }    }}
复制代码

SwiftData 2027 版本还引入了 ResultObserver,它提供了一种类似 @Query 的机制,但可以在 SwiftUI 之外使用。这使其适用于需要根据数据变化重新计算值的对象类场景,或者完全不使用 SwiftUI 的环境,例如基于 SceneKit 的应用。ResultObserver 基于 Observation 框架构建,并支持与 @Query 相同的功能,包括排序、过滤以及分区。

下面的代码片段展示了如何定义一个控制器对象,并使用 ResultObserver 观察 Trip 实体的变化:

@Observable @MainActor final class MapCameraController {    private let ResultObserver: ResultObserver<Trip>    ...    private var token: ObservationTracking.Token?    init(modelContext: ModelContext) throws {        resultObserver = try ResultObserver<Trip>(modelContext: modelContext)        token = withContinuosObservation(option: [.didSet]) { [weak self] event in            ...        }    }}
复制代码

与 ResultsObserver 类似,HistoryObserver 会监控数据存储的持久化历史记录,并允许代码在新增事务时做出响应。这对于保持数据存储的一部分内容与其他系统同步非常有用,例如远程服务器。HistoryObserver 提供了一个可观察的 eventCounter 属性,每当持久化历史记录中出现新的事务时,该属性都会递增。通过观察这一属性,应用可以使用 ModelContext.fetchHistory API 获取最新变化。

面向苹果 2027 平台版本的 SwiftData 已经可以在 Xcode 27 beta 中使用。

原文连接:https://www.infoq.com/news/2026/07/swiftdata-27-whats-new/