Filtering data with predicates

A typical operation you'll want to perform on your database is filtering. In Core Data, you use predicates to do this. A predicate describes a set of rules that any object that gets fetched has to match.

When you model your data in the model editor, it's wise to think about the types of filtering you need to do. For instance, you may be building a birthday calendar where you'll often sort or filter by date. If this is the case, you should make sure that you have a Core Data index for this property. You can enable indexing with the checkbox you saw earlier in the model editor. If you ask Core Data to index a property, it will significantly improve performance when filtering and selecting data in large datasets.

Writing predicates can be confusing, especially if you try to think of them as the where clause from SQL. Predicates are very similar, but they're not quite the same. A simple predicate looks as follows:

NSPredicate(format: "name CONTAINS[n] %@", "Gu") 

A predicate has a format; this format always starts with a key. This key represents the property you want to match on. In this example, it would be the name of a family member. Then, you specify the condition, for instance ==, >, <, or CONTAINS[n]. There are more conditions available, but the ones listed are some examples of conditions you'll commonly use. Finally, you will specify a placeholder that is substituted with the true value. This placeholder is %@ in the preceding sample. If you have written any Objective-C before you picked up this book, the %@ placeholder might look familiar to you because it's used as a placeholder in format strings there.

The example predicate is very simple and bare; it could be the template for a search feature you're building. Usually, a simple search doesn't have to be much more complicated than this as long as there's an index added to the properties you search for.

If you have multiple predicates you want to match on, you can combine them using NSCompoundPredicate. This class combines different predicates using either an and, or, or not clause. A typical use case for this approach is when you build a complex filter in your app where the predicate is hard to express in a single statement.

To use a predicate in a fetch request, you assign it to the predicate property of a fetch request. Every fetch request has a predicate property that you can set. It can handle both a single predicate and a compound predicate. If you set this property before executing the fetch request, the predicate is applied to the request, and you will receive a filtered dataset instead of the full dataset.

Predicates are powerful, and they have many options available.

If you're interested in an in-depth overview of predicates and all of the ways in which you can make use of format strings, I recommend that you read Apple's Predicate Programming Guide at http://apple.co/2fF3qHc. It provides a well-documented overview of predicates and their applications.

Next up, you will learn how to respond to changes in the managed object context. For instance, when you add new family members and movies.