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:
- Get Object By ID
- Fetch A Single Object
- Filter Fetch Request With Predicate
- Filter Predicate With Multiple Conditions
- Fetch All Objects Of One Entity
- 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:
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:
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.