views:

63

answers:

1

hi everyone,

i've got a NSMutableArray created from a data source object

NSMutableArray *mutableFetchResults = [[managedObjectContext executeFetchRequest:request error:&error] mutableCopy]; 

[self setAmountArray: mutableFetchResults];

every object in my mutable array has the two instance variables name and timeadded.

now i want to display all names in a uitableview grouped by the day they are added. for that i wrote the following method

-(NSMutableArray*)arrangeTransfersByDate:(NSMutableArray*)transferArray {

    // Setting up objects for this method
    NSDate *oldDate = [NSDate dateWithTimeIntervalSince1970:0.0f];
    NSDateFormatter *dateComparisonFormatter = [[NSDateFormatter alloc] init];
    [dateComparisonFormatter setDateFormat:@"yyyy-MM-dd"];
    NSMutableArray *returnArray = [[NSMutableArray alloc] init];

    for(transfers *transfer in transferArray) {

        if( [[dateComparisonFormatter stringFromDate:[transfer timeadded]] isEqualToString:[dateComparisonFormatter stringFromDate:oldDate]] ) {
            if([returnArray count] == 0) {
                [returnArray addObject:[NSMutableArray arrayWithObject:transfer]];
            } else {
                [[returnArray objectAtIndex:[returnArray count]-1] addObject:transfer];
            }
        } else {
            [returnArray addObject:[NSMutableArray arrayWithObject:transfer]];
            oldDate = [transfer timeadded];
        }

    }
    //[returnArray release];
    [dateComparisonFormatter release];
    return returnArray;


}

transferArray is my amountArray where my core data objects are stored.

so this works! but

is there a better way to do this? can you give me something like a "best practise" or simply have a look if there are some memory leaks?

thanks!


edit:

the right answer was NSFetchedResultController and its sectionNameKeyPath.

however i don't wanted to store my data twice a time.

so i created the following getter method in my NSManagedObject.

- (NSString *) pubDate {

    [self willAccessValueForKey:@"pubDate"];

    NSDateFormatter *dateComparisonFormatter = [[NSDateFormatter alloc] init];
    [dateComparisonFormatter setDateFormat:@"dd.MM.YYYY"];
    NSString *temp = [dateComparisonFormatter stringFromDate:[self pubTime]];
    [dateComparisonFormatter release];

    [self didAccessValueForKey:@"pubDate"];

    return temp;
}

with this i can sort my tableviewcontroller by date using my FetchedResultController and my pubTime which is a timestamp.

[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest 
                                              managedObjectContext:[self managedObjectContext] 
                                                sectionNameKeyPath:@"pubDate" 
                                                         cacheName:@"transfersRoot"];

thanks to all

+1  A: 

Generally when you want to display the results of a Core Data fetch in a UITableView, you use an NSFetchedResultsController. You can choose the attribute by which you want to group your results by specifying a sectionNameKeyPath during initialization.

That said, provided your method works then really it's up to you whether you want to change your code around or not.

But please make sure you [returnArray autorelease] before you return it. It's a generally accepted Objective-C practice that any method without "alloc", "new", or "copy" in the name will return an autoreleased object.

robinjam
wow `NSFetchedResultsController` looks good. but how to use `sectionNameKeyPath` on a timestamp, that is always different? also thanks for the autorelease tip!
choise
I'm guessing that your `transfers` class is the entity class for your data model? Well you could add a property to that, which extracts the date from the timestamp, and then pass that property's key path as `sectionNameKeyPath`.
robinjam
you are right. i also need the exact timestamp, so you think i should double entry the date? once as real timestamp and one as only the date in my database? hm
choise
The `date` property will only be used to generate section titles. You can still use your timestamp wherever you need to. And the date won't be stored in your database, it should be generated at runtime.
robinjam
shure. i only thought about database normalization and about storing the "same" value two times in a row.
choise
Core Data is ***NOT*** a database. It is an Object Graph that happens to persist to a database if you choose to. Database normalization is usually counter-intuitive when it comes to Core Data. You **should** store the NSDate and a NSString representation in the database and use that as your section keypath.
Marcus S. Zarra
Why would storing the NSString representation be preferable over generating it at runtime?
robinjam
check my edit above for my solution. thanks for your great help
choise
@ Marcus Zarra: i don't really understand why it is "counter-intuitive"? isn't it the best thing to prevent my app from storing my data twice? thanks for your great article at "PragPub", this article really helped me, to solve this issue super fast :)
choise