Using Predicate in Swift
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
In Swift, using a predicate usually means using NSPredicate with Foundation, Core Data, or another Cocoa API that expects a predicate object. It is a reusable condition that describes which objects match and which do not. The key decision is whether you are working with Objective-C-style APIs that need NSPredicate, or with pure Swift collections where a closure is usually clearer.
Use NSPredicate When the API Expects It
NSPredicate is common when filtering NSArray, NSFetchedResultsController, and Core Data fetch requests.
This style depends on key-value coding, so it works best with Foundation objects and models that are visible to Objective-C runtime features. That is why it still appears frequently in Apple platform code even when most of the surrounding project is written in modern Swift.
Core Data Is a Natural Fit
One of the best uses for predicates is narrowing a Core Data fetch request before data is loaded into memory.
You can also combine conditions:
Filtering at the fetch layer is usually better than loading everything and filtering later in Swift. It reduces work, reduces memory use, and keeps the query intent close to the data source.
Prefer filter for Pure Swift Collections
If you are dealing with normal Swift structs and arrays, a closure is usually the better option.
This is type-safe and compiler-checked. If you rename age, the compiler tells you what broke. A format-string predicate cannot do that, which is one reason it should not be the default for ordinary Swift collection filtering.
Use Compound Predicates for More Complex Rules
When a Foundation API requires a predicate and the matching logic has several parts, compose smaller predicates instead of writing one opaque string.
This is easier to maintain than a very long predicate string with multiple operators and substitutions.
Block-Based Predicates Are Sometimes Safer
NSPredicate also supports block-based construction, which avoids format-string syntax when the logic is easier to write in Swift.
This is useful when you need richer matching logic, though it is less portable to APIs that want a serializable predicate expression.
Keep the Boundary Clear
A lot of confusion around predicates comes from using the wrong tool at the wrong layer. NSPredicate is valuable because some Apple APIs are designed around it. That does not mean every collection filter in Swift should become a predicate string.
If the job is local in-memory filtering of Swift values, prefer closures. If the job is configuring a Cocoa or Core Data API that expects NSPredicate, use it directly and keep the expression as simple as possible.
Common Pitfalls
- Using
NSPredicatefor ordinary Swift arrays whenfilterwith a closure would be simpler and safer. - Misspelling property names inside a format string and losing compiler help.
- Filtering after fetching large Core Data result sets instead of filtering in the fetch request.
- Writing one very long predicate string when smaller compound predicates would be easier to maintain.
- Mixing Swift value types and Objective-C-style predicate assumptions without checking API compatibility.
Summary
- '
NSPredicateis the right tool when Foundation or Core Data APIs require a predicate object.' - For normal Swift arrays,
filteris usually the clearer and safer choice. - Core Data predicates are most useful when they narrow results before fetch.
- '
NSCompoundPredicatehelps keep multi-part conditions readable.' - Choose predicates based on the API boundary, not just because the feature exists.

