Filtering Core Data
Learn how to filter Core Data fetch requests using NSPredicate to retrieve specific data based on attributes like an ID.
Swift Tutorial #18 — Filtering Core Data
Note:
This tutorial covers how to use NSPredicate to filter your Core Data fetch requests and retrieve only the data you need.
Overview
Entities in Core Data can have various attributes, and often you don't want to fetch all the data at once. One of the most effective ways to filter this data is by using an NSPredicate within your fetch request. This allows you to specify conditions that objects must meet to be returned.
In this example, we'll demonstrate how to fetch a specific item from Core Data based on its unique ID, which might have been selected from a UITableView.
Reference:
Using NSPredicate to Filter a Fetch Request
An NSPredicate is an object that specifies how data should be fetched or filtered. You can think of it as the WHERE clause in a SQL query.
Let's say a user taps an item in a UITableView, and you want to fetch only that specific item's details from Core Data on the next screen. You would pass the unique id of the selected item to the details view controller. Then, you can use that id to create a predicate and filter your fetch request.
The Code
Here’s how you would structure your getData function in the DetailsViewController:
- Get the
id: First, ensure you have theidof the object you want to fetch. This would typically be passed from the previous view controller. - Create a Fetch Request: As before, create an
NSFetchRequestfor your entity. - Create and Assign the Predicate: Create an
NSPredicatewith a format string that defines your filter. The format%@is a placeholder for an argument. - Execute the Fetch: Fetch the data. The result will be an array containing only the objects that match the predicate.
// In your DetailsViewController
var selectedID: UUID? // This would be passed from the previous ViewController
func getData() {
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
let context = appDelegate.persistentContainer.viewContext
// 1. Create the fetch request
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Shopping")
// 2. Create the predicate to filter by ID
// Note: Use 'idString' if your ID is a String, or 'id' if it's a UUID
if let id = selectedID {
let idString = id.uuidString
fetchRequest.predicate = NSPredicate(format: "id_string_attribute == %@", idString)
}
fetchRequest.returnsObjectsAsFaults = false
// 3. Execute the fetch request
do {
let results = try context.fetch(fetchRequest)
if results.count > 0 {
// We expect only one result since IDs are unique
if let result = results[0] as? NSManagedObject {
// Now you have the specific object and can access its properties
if let name = result.value(forKey: "name") as? String {
// Update your UI with the name
// nameLabel.text = name
}
if let size = result.value(forKey: "size") as? String {
// Update your UI with the size
// sizeLabel.text = size
}
}
}
} catch {
print("Error fetching filtered data: \(error)")
}
}
By using a predicate, we have successfully retrieved only the specific object we were interested in, making our data access more efficient and targeted.
Note:
NSPredicate is incredibly powerful and supports a wide range of operators, including BEGINSWITH, CONTAINS, LIKE, as well as compound predicates using AND and OR.