waylonion
waylonion

Reputation: 6976

Filter/Sort Core Data into Array

I have a core data model with an entity named Expense. It contains an attribute named time which stores an NSDate.

What's an efficient way of sorting all of these Expenses into a single NSMutableArray categorized by month?

For example, if there are five expenses with the following dates:

1 1/6/2014

2 2/4/2014

3 5/2/2014

4 6/5/2014

5 9/4/2014

An NSMutableArray should be returned holds a bunch of arrays. Each array represents 1 month which holds all the entities attributed to it.

Upvotes: 0

Views: 202

Answers (3)

fumoboy007
fumoboy007

Reputation: 5553

Example:

// Get expenses from Core Data
NSArray *expensesToCategorize = ...;

// Create calendar
static NSCalendar *gregorian = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
    gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
});

// Set time zone of calendar
[gregorian setTimeZone:[NSTimeZone defaultTimeZone]];

// Group expenses by month
NSMutableDictionary *expensesByMonth = [[NSMutableDictionary alloc] init];
for (Expense *expense in expensesToCategorize) {
    NSDate *date = expense.time;

    NSDateComponents *components = [gregorian components:(NSYearCalendarUnit | NSMonthCalendarUnit) fromDate:date];
    [components setDay:1];

    NSDate *firstDayOfMonth = [gregorian dateFromComponents:components];

    NSMutableArray *expensesThisMonth = expensesByMonth[firstDayOfMonth];
    if (!expensesThisMonth) {
        expensesThisMonth = [[NSMutableArray alloc] init];
        expensesByMonth[firstDayOfMonth] = expensesThisMonth;
    }

    [expensesThisMonth addObject:expense];
}

// Transform into desired data structure
NSArray *sortedMonthDates = [[expensesByMonth allKeys] sortedArrayUsingSelector:@selector(compare:)];
NSArray *categorizedExpenses = [expensesByMonth objectsForKeys:sortedMonthDates notFoundMarker:[NSNull null]];

// Sort expenses within each month by date
for (NSMutableArray *expensesThisMonth in categorizedExpenses) {
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"time" ascending:YES];
    [expensesThisMonth sortUsingDescriptors:@[sortDescriptor]];
}

Upvotes: 1

Mindeater
Mindeater

Reputation: 322

Are you looking for a fetchedResultsController ?

For example the following code populates a fetchedResultsController for use in a Grouped TableViewController

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Location"
                                              inManagedObjectContext:_managedObjectContext];
    [fetchRequest setEntity:entity];

    [fetchRequest setSortDescriptors:@[
     [[NSSortDescriptor alloc] initWithKey:@"map_name" ascending:YES],
     [[NSSortDescriptor alloc] initWithKey:@"order_num" ascending:YES]
     ]];

    [fetchRequest setFetchBatchSize:20];


    // Use the sectionIdentifier property to group into sections.

    _fetchedResultsController =
    [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
                                        managedObjectContext:_managedObjectContext
                                          sectionNameKeyPath:@"map_name"
                                                   cacheName:@"LocationsList"];

Upvotes: 0

Sunny Shah
Sunny Shah

Reputation: 13020

Array With Custom Objects

NSArray *sorted = [arr sortedArrayUsingFunction:dateSort context:nil];

Sort Function

NSComparisonResult dateSort(Class *s1, Class *s2, void *context) {
NSDate *d1 = [Utility getDateFromTheString:s1.strDate];
NSDate *d2 = [Utility getDateFromTheString:s2.strDate];
return -1*[d1 compare:d2];

}

Convert String into Date

 +(NSDate *)getDateFromTheString:(NSString *)strDate{
    NSDateFormatter* dateFormat = [[NSDateFormatter alloc] init];
    [dateFormat setTimeZone:[NSTimeZone timeZoneWithName:@"GMT"]];
    [dateFormat setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"en_US"]];
    [dateFormat setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
    NSDate *date = [dateFormat dateFromString:strDate];
    return date;
}

Upvotes: 1

Related Questions