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.
