Skip to content
Permalink
master
Go to file
 
 
Cannot retrieve contributors at this time
266 lines (198 sloc) 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)
You can’t perform that action at this time.