QueryKit, a simple type-safe Core Data query language.
QuerySet<Person>(context, "Person")
.orderedBy(.name, ascending: true)
.filter(\.age >= 18)
A QuerySet represents a collection of objects from your Core Data Store. It may have zero, one or many filters. Filters narrow down the query results based on the given parameters.
let queryset = QuerySet<Person>(context, "Person")
You may filter a QuerySet using the filter
and exclude
methods, which
accept a predicate which can be constructed using KeyPath extensions.
The filter
and exclude
methods return new QuerySet's including your filter.
queryset.filter(\.name == "Kyle")
queryset.exclude(\.age > 25)
You may also use standard NSPredicate
if you want to construct complicated
queries or do not wish to use the type-safe properties.
queryset.filter(NSPredicate(format: "name == '%@'", "Kyle"))
queryset.exclude(NSPredicate(format: "age > 25"))
The result of refining a QuerySet is itself a QuerySet, so it’s possible to chain refinements together. For example:
queryset.filter(\.name == "Kyle")
.exclude(\.age < 25)
Each time you refine a QuerySet, you get a new QuerySet instance that is in no way bound to the previous QuerySet. Each refinement creates a separate and distinct QuerySet that may be stored, used and reused.
A QuerySet is lazy, creating a QuerySet doesn’t involve querying Core Data. QueryKit won’t actually execute the query until the QuerySet is evaluated.
You may order a QuerySet's results by using the orderBy
function which
accepts a KeyPath.
queryset.orderBy(\.name, ascending: true)
You may also pass in an NSSortDescriptor
if you would rather.
queryset.orderBy(NSSortDescriptor(key: "name", ascending: true))
Using slicing, a QuerySet's results may be limited to a specified range. For example, to get the first 5 items in our QuerySet:
queryset[0...5]
NOTE: Remember, QuerySets are lazily evaluated. Slicing doesn’t evaluate the query.
You may convert a QuerySet to an array using the array()
function. For example:
for person in try! queryset.array() {
println("Hello \(person.name).")
}
let kyle = try? queryset.first()
let kyle = try? queryset.last()
let katie = try? queryset.object(3)
let numberOfPeople = try? queryset.count()
This method immediately deletes the objects in your queryset and returns a count or an error if the operation failed.
let deleted = try? queryset.delete()
QueryKit provides KeyPath extensions providing operator functions allowing you to create predicates.
// Name is equal to Kyle
\Person.name == "Kyle"
// Name is either equal to Kyle or Katie
\.Person.name << ["Kyle", "Katie"]
// Age is equal to 27
\.Person.age == 27
// Age is more than or equal to 25
\Person.age >= 25
// Age is within the range 22 to 30.
\Person.age << (22...30)
The following types of comparisons are supported using Attribute:
Comparison | Meaning |
---|---|
== | x equals y |
!= | x is not equal to y |
< | x is less than y |
<= | x is less than or equal to y |
> | x is more than y |
>= | x is more than or equal to y |
~= | x is like y |
~= | x is like y |
<< | x IN y, where y is an array |
<< | x BETWEEN y, where y is a range |
QueryKit provides the !
, &&
and ||
operators for joining multiple predicates together.
// Persons name is Kyle or Katie
\Person.name == "Kyle" || \Person.name == "Katie"
// Persons age is more than 25 and their name is Kyle
\Person.age >= 25 && \Person.name == "Kyle"
// Persons name is not Kyle
!(\Person.name == "Kyle")
CocoaPods is the recommended way to add QueryKit to your project, you may also use Carthage.
pod 'QueryKit'
QueryKit is released under the BSD license. See LICENSE.