Skip to content

Latest commit

 

History

History
266 lines (198 loc) · 8.87 KB

Fetching-Entities.md

File metadata and controls

266 lines (198 loc) · 8.87 KB

Fetching Entities

Basic Finding

Most methods in MagicalRecord return an NSArray of results.

As an example, if you have an entity named Person related to a Department entity (as seen in many of Apple's Core Data examples), you can retrieve all of the Person entities from your persistent store using the following method:

// Objective-C
NSArray *people = [Person MR_findAll];
// Swift
let people = Person.mr_findAll()

To return the same entities sorted by a specific attribute:

// Objective-C
NSArray *peopleSorted = [Person MR_findAllSortedBy:@"LastName"
                                         ascending:YES];
// Swift
let peopleSorted = Person.mr_findAllSorted(by: "LastName", ascending: true)

To return the entities sorted by multiple attributes:

// Objective-C
NSArray *peopleSorted = [Person MR_findAllSortedBy:@"LastName,FirstName"
                                         ascending:YES];
// Swift
let peopleSorted = Person.mr_findAllSorted(by: "LastName,FirstName", ascending: true)

To return the results sorted by multiple attributes with different values. If you don't provide a value for any attribute, it will default to whatever you've set in your model:

// Objective-C
NSArray *peopleSorted = [Person MR_findAllSortedBy:@"LastName:NO,FirstName"
                                         ascending:YES];

// OR

NSArray *peopleSorted = [Person MR_findAllSortedBy:@"LastName,FirstName:YES"
                                         ascending:NO];
// Swift
let peopleSorted = Person.mr_findAllSorted(by: "LastName:NO,FirstName", ascending: true)

// OR

let peopleSorted = Person.mr_findAllSorted(by: "LastName,FirstName:YES", ascending: false)

If you have a unique way of retrieving a single object from your data store (such as an identifier attribute), you can use the following method:

// Objective-C
Person *person = [Person MR_findFirstByAttribute:@"FirstName"
                                       withValue:@"Forrest"];
// Swift
let person = Person.mr_findFirst(byAttribute: "FirstName", withValue: "Forrest")

Advanced Finding

If you want to be more specific with your search, you can use a predicate:

// Objective-C
NSPredicate *peopleFilter = [NSPredicate predicateWithFormat:@"Department IN %@", @[dept1, dept2]];
NSArray *people = [Person MR_findAllWithPredicate:peopleFilter];
// Swift
let peopleFilter = NSPredicate(format: "Department IN %@", [dept1, dept2])
let people = Person.mr_findAll(with: peopleFilter)

Returning an NSFetchRequest

// Objective-C
NSPredicate *peopleFilter = [NSPredicate predicateWithFormat:@"Department IN %@", departments];
NSFetchRequest *people = [Person MR_requestAllWithPredicate:peopleFilter];
// Swift
let peopleFilter = NSPredicate(format: "Department IN %@", departments)
let people = Person.mr_requestAll(with: peopleFilter)

For each of these single line calls, an NSFetchRequest and NSSortDescriptors for any sorting criteria are created.

Customizing the Request

// Objective-C
NSPredicate *peopleFilter = [NSPredicate predicateWithFormat:@"Department IN %@", departments];

NSFetchRequest *peopleRequest = [Person MR_requestAllWithPredicate:peopleFilter];
[peopleRequest setReturnsDistinctResults:NO];
[peopleRequest setPropertiesToFetch:@[@"FirstName", @"LastName"]];

NSArray *people = [Person MR_executeFetchRequest:peopleRequest];
// Swift
let peopleFilter = NSPredicate(format: "Department IN %@", departments)

let peopleRequest = Person.mr_requestAll(with: peopleFilter)
peopleRequest.returnsDistinctResults = false
peopleRequest.propertiesToFetch = ["FirstName", "LastName"]

let people = Person.mr_executeFetchRequest(peopleRequest)

Find excluding subentities

To fetch all sorted, excluding subentities:

// Objective-C
NSFetchRequest *peopleRequest = [Person MR_requestAllSortedBy:@"LastName" ascending:YES withPredicate:nil];
NSFetchedResultsController *controller = [Person MR_fetchController:peopleRequest delegate:nil useFileCache:NO groupedBy:nil inContext:[NSManagedObjectContext MR_defaultContext]];
controller.fetchRequest.includesSubentities = NO;
[Person MR_performFetch:controller];

NSArray *people = controller.fetchedObjects;
// Swift
let peopleRequest = Person.mr_requestAllSorted(by: "LastName", ascending: true, with: nil)
let controller = Person.mr_fetchController(peopleRequest, delegate: nil, useFileCache: false, groupedBy: nil, in: NSManagedObjectContext.mr_default())
controller.fetchRequest.includesSubentities = false
Person.mr_performFetch(controller)

let people = controller.fetchedObjects

Note: MR_defaultContext/mr_default() is for main thread. See Working-with-Managed-Object-Contexts.md for other contexts.

Find the number of entities

You can also perform a count of all entities of a specific type in your persistent store:

// Objective-C
NSNumber *count = [Person MR_numberOfEntities];
// Swift
let count = Person.mr_numberOfEntities()

Or, if you're looking for a count of entities based on a predicate or some filter:

// Objective-C
NSNumber *count = [Person MR_numberOfEntitiesWithPredicate:...];
// Swift
let count = Person.mr_numberOfEntities(with: ...)

There are also complementary methods which return NSUInteger (UInt in Swift) rather than NSNumber instances:

// Objective-C
+ (NSUInteger) MR_countOfEntities;
+ (NSUInteger) MR_countOfEntitiesWithContext:(NSManagedObjectContext *)context;
+ (NSUInteger) MR_countOfEntitiesWithPredicate:(NSPredicate *)searchFilter;
+ (NSUInteger) MR_countOfEntitiesWithPredicate:(NSPredicate *)searchFilter
                                     inContext:(NSManagedObjectContext *)context;
// Swift
open class func mr_countOfEntities() -> UInt
open class func mr_countOfEntities(with context: NSManagedObjectContext) -> UInt
open class func mr_countOfEntities(with searchFilter: NSPredicate?) -> UInt
open class func mr_countOfEntities(with searchFilter: NSPredicate?,
                                   in context: NSManagedObjectContext) -> UInt

Aggregate Operations

// Objective-C
NSNumber *totalCalories = [CTFoodDiaryEntry MR_aggregateOperation:@"sum:"
                                                      onAttribute:@"calories"
                                                    withPredicate:predicate];

NSNumber *mostCalories  = [CTFoodDiaryEntry MR_aggregateOperation:@"max:"
                                                      onAttribute:@"calories"
                                                    withPredicate:predicate];

NSArray *caloriesByMonth = [CTFoodDiaryEntry MR_aggregateOperation:@"sum:"
                                                       onAttribute:@"calories"
                                                     withPredicate:predicate
                                                           groupBy:@"month"];
// Swift
let totalCalories = CTFoodDiaryEntry.mr_aggregateOperation("sum:",
                                                           onAttribute: "calories",
                                                           with: predicate)

let mostCalories = CTFoodDiaryEntry.mr_aggregateOperation("max:",
                                                          onAttribute: "calories",
                                                          with: predicate)

let caloriesByMonth = CTFoodDiaryEntry.mr_aggregateOperation("sum:",
                                                             onAttribute: "calories",
                                                             with: predicate,
                                                             groupBy: "month")

Finding entities in a specific context

All find, fetch, and request methods have an inContext: method parameter that allows you to specify which managed object context you'd like to query:

// Objective-C
NSArray *peopleFromAnotherContext = [Person MR_findAllInContext:someOtherContext];

Person *personFromContext = [Person MR_findFirstByAttribute:@"lastName"
                                                  withValue:@"Gump"
                                                  inContext:someOtherContext];

NSUInteger count = [Person MR_numberOfEntitiesWithContext:someOtherContext];
// Swift
let peopleFromAnotherContext = Person.mr_findAll(in: someOtherContext)

let personFromContext = Person.mr_findFirst(byAttribute: "lastName",
                                            withValue: "Gump",
                                            in: someOtherContext)

let count = Person.mr_numberOfEntities(with: someOtherContext)