Query 是一个用于 Core Data 的流畅式查询构建器。
安装通过 Swift Package Manager 完成。将此仓库的 URL 粘贴到 Xcode 中,或将此行添加到您的 Package.swift
.package(url: "https://github.com/lightyear/Query", from: "1.0.0")
查询 Core Data 管理对象上下文涉及大量样板代码。此包提供了一个新的 Query<T>
类型,它是一个流畅式、可链式调用的查询构建器
class Entity: NSManagedObject { ... }
try Entity.query(in: someManagedObjectContext)
.where("quantity == 1")
.order(by: "date")
.all()
// result is [Entity] or a thrown error
如果您的托管对象子类也遵循 Queryable
协议并提供嵌套的 Attribute
类型,则可以使用 .where()
和 .order()
的其他重载,这些重载接受可以由编译器检查的属性,而不是字符串
extension Entity: Queryable {
enum Attribute {
case quantity, date
}
}
try Entity.query(in: someManagedObjectContext)
.where([.quantity: 1])
.order(by: .date)
.all()
// result is [Entity] or a thrown error
(SR-5220 Expose API to retrieve string representation of KeyPath 是支持类似功能的更好方法。如果我们最终实现了它,Queryable
将会被弃用。)
基本的过滤谓词是 .where()
。它接受与 NSPredicate
相同的参数,或者,如果托管对象子类遵循 Queryable
,则接受另一个版本,该版本接受由属性键控的 Dictionary
where("quantity == 1")
where("quantity == %d", 1)
where("name == %@", "Alice")
where("%K == %@", "name", "Alice")
where([.quantity: 1])
where([.name: "Alice"])
链式调用 .where()
会使用 AND 组合
where("quantity == 1").where("name == %@", "Alice")
// same as where("quantity == 1 AND name == %@", "Alice")
还有 .or()
where("quantity == 1").or("name == %@", "Alice")
// same as where("quantity == 1 OR name == %@", "Alice")
当与 .where()
结合使用时,.or()
会将之前的所有内容视为包裹在一组括号中。
where("quantity == 1").where("name == %@", "Alice").or("name == %@", "Bob")
// same as where("(quantity == 1 AND name == %@) OR name == %@", "Alice", "Bob")
.where()
和 .or()
的字典形式支持值和范围周围的不等式包装器
where([.quantity: lt(1)]) // same as where("quantity < 1")
where([.quantity: 1...3]) // same as where("quantity BETWEEN (1,3)")
添加一个或多个排序描述符通过 order()
完成
order(by: "department").order(by: "name")
默认排序顺序是升序,但降序也是一个选项
order(by: "quantity", .descending)
字符串值也可以不区分大小写地排序,或使用本地化比较进行排序
order(by: "name", .ascending, .localizedCaseInsensitive)
order(by: "name", .ascending, .localizedStandard)
所有匹配的结果(如果指定了排序)都通过调用 .all()
获取。如果您只想获取第一个匹配结果,请使用 .first()
。如果您只关心匹配对象的数量,请使用 .count()
。
如果您的托管对象子类遵循 Queryable
,您使用不带不等式或 .or()
条件的类型化 Attribute
版本的 .where()
,.firstOrInsert()
将获取第一个匹配项,或者将一个新实例插入到上下文中,并将其属性设置为查询条件。在初始值不确定的情况下,它会抛出 QueryError.tooComplex
错误。
如果您需要与当前查询匹配的真实 NSFetchRequest
,您可以从 fetchRequest
属性中获取它。这对于进一步自定义 fetch 请求或将其传递给 NSFetchedResultsController
非常有用。
也遵循 Identifiable
的托管对象子类获得了一些额外的查询功能。如果上下文中存在具有提供的 ID 的对象,则 exists(_:)
返回 true
。
fetch(_:)
返回具有提供的 ID 的实例,如果上下文中不存在具有该 ID 的对象,则返回 nil
。
fetchOrInsert(_:)
返回具有提供的 ID 的实例,或者,如果尚不存在具有该 ID 的对象,则返回一个 id
属性设置为该 ID 的新实例。