Core Data is a powerful database framework for iOS and macOS apps. This post presents examples of making queries using fetch requests for Core Data objects in Swift:

  1. Get Object By ID
  2. Fetch A Single Object
  3. Filter Fetch Request With Predicate
  4. Filter Predicate With Multiple Conditions
  5. Fetch All Objects Of One Entity
  6. Fetch Request Multiple Entities

Note: in this post persistentContainer will be used to refer to an initialized instance of NSPersistentContainer.

Get Object By ID

To get an object by ID in Core Data, use the existingObject(with:) function on an instance of NSManagedObjectContext:

// Get the managed object ID of the object
let managedObject = // ... an NSManagedObject
let managedObjectID = managedObject.objectID

// Get a reference to a NSManagedObjectContext
let context = persistentContainer.viewContext

// Get the object by ID from the NSManagedObjectContext         
let object = try context.existingObject(
    with: managedObjectID
)

Fetch A Single Object

To fetch an object in Core Data, limit a NSFetchRequest to return one result. Then, use the fetch(_:) function on an instance of NSManagedObjectContext:

// Configure a fetch request to fetch at most 1 result
let fetchRequest = // An NSFetchRequest
fetchRequest.fetchLimit = 1

// Get a reference to a NSManagedObjectContext
let context = persistentContainer.viewContext

// Fetch a single object. If the object does not exist,
// nil is returned
let object = try context.fetch(fetchRequest).first

Filter Fetch Request With Predicate

To add a filter to a Core Data fetch request, add a predicate. Then, use the fetch(_:) function on an instance of NSManagedObjectContext:

// Create a fetch request with a string filter 
// for an entity’s name  
let fetchRequest: NSFetchRequest<Entity> 
fetchRequest = Entity.fetchRequest()

fetchRequest.predicate = NSPredicate(
    format: "name LIKE %@", "Robert"
)

// Get a reference to a NSManagedObjectContext
let context = persistentContainer.viewContext

// Perform the fetch request to get the objects
// matching the predicate
let objects = try context.fetch(fetchRequest)

You can see more examples of filter fetch requests with NSPredicate in the following article:

Swift Core Data String Queries
Learn how to find an exact string, regex search, and more in Core Data.

Filter Predicate With Multiple Conditions

A compound predicate can contain multiple conditions to create a complex fetch request in Core Data. Set a compound predicate on a fetch request and then use the fetch(_:) function on an instance of NSManagedObjectContext:

// Create a fetch request with a compound predicate
let fetchRequest: NSFetchRequest<Entity> 
fetchRequest = Entity.fetchRequest()

// Create the component predicates
let namePredicate = NSPredicate(
    format: "name LIKE %@", "Robert"
)

let planetPredicate = NSPredicate(
    format: "country = %@", "Earth"
)

// Create an "and" compound predicate, meaning the 
// query requires all the predicates to be satisfied.
// In other words, for an object to be returned by 
// an "and" compound predicate, all the component 
// predicates must be true for the object.
fetchRequest.predicate = NSCompoundPredicate(
    andPredicateWithSubpredicates: [
        namePredicate, 
        planetPredicate
    ]
)

// Get a reference to a NSManagedObjectContext
let context = persistentContainer.viewContext

// Perform the fetch request to get the objects 
// matching the compound predicate
let objects = try context.fetch(fetchRequest)

Fetch All Objects Of One Entity

The fetchRequest() function is available on subclasses of NSManagedObject in Core Data. Using fetchRequest() on a Core Data entity creates a fetch request for all objects of that entity type:

// Create a fetch request for a specific Entity type
let fetchRequest: NSFetchRequest<Entity> 
fetchRequest = Entity.fetchRequest()

// Get a reference to a NSManagedObjectContext
let context = persistentContainer.viewContext

// Fetch all objects of one Entity type
let objects = try context.fetch(fetchRequest)

Fetch Request Multiple Entities

One way to create a fetch request targeting multiple entities is to add a shared parent class to multiple entities. For example, a NamedEntity can be created with a String property name.

Then, the Parent entity can be set to NamedEntity in the Entity Inspector in Xcode:

Core Data Entity Inspector In Xcode Showing A Parent Entity

In this example, NamedEntity is set as the parent class of the Business entity and Brand entity. The fetch request in the example will return Business entities and Brand entities with a name property equal to "Apple".

// Create a fetch request for a NamedEntity
let fetchRequest: NSFetchRequest<NamedEntity> 
fetchRequest = NamedEntity.fetchRequest()

// Add a predicate for entities with a name 
// attribute equal to "Apple"
fetchRequest.predicate = NSPredicate(
    format: "name LIKE %@", "Apple"
)

// Get a reference to a NSManagedObjectContext
let context = persistentContainer.viewContext

// Perform the fetch request to get the objects 
// matching the predicate
let objects = try context.fetch(fetchRequest)

// Handle multiple entity types
for object in objects {
    if let object = object as? Business {
        print("Business:", object.name)
    }
    else if let object = object as? Brand {
        print("Person:", object.name)
    }
}

Core Data Queries in Swift

That's it! By using NSFetchRequest and NSPredicate you can make queries and filter by ID, predicate, entity in Core Data using Swift.