Comparison function for Core Data NSFetchedResultsController - core-data

I am using NSFetchedResultsController to section my data into separate sections. The main sortDescriptor I give is this:
NSSortDescriptor *sortDescriptorSectionLetter = [[NSSortDescriptor alloc] initWithKey:#"sectionLetter" ascending:YES selector:#selector(localizedCompare:)];
Now my sectionLetter has a default value of "#". When the tableView is sectioned and presented, it places the '#' section at the top of the table. I want this to show up at the bottom of the list (like the Contacts app does it). But I can't figure out how to accomplish this.
I've also tried different types of characters as the default instead of #, like � and ~, but this doesn't seem to work either. According to the Core Data Programming Guide, I can't pass in a customized comparison function here.
So I'm not sure what my options are here (other than doing the sectioning myself and losing all the FRC delegate goodness to reload my tableviews with animation). Any good ideas?

Notice the remark in the documentation for NSFetchedResultsController:
Subclassing Notes
You create a subclass of this class if you want to customize the creation of sections and index titles. You override sectionIndexTitleForSectionName: if you want the section index title to be something other than the capitalized first letter of the section name. You override sectionIndexTitles if you want the index titles to be something other than the array created by calling sectionIndexTitleForSectionName: on all the known sections.

Related

Multiple cells with multiple textfields to core data attributes

I have a tableview with 9 cells and in each cell i have at least 2 textfields. Each cell has a label, and the textfields.placeholder are the same in each cell:(example foto below)
I already created the entities in core data (which are the labels) and the attributes for each one ( which are the textfields.placeholder):
My question is, how can i set the textfield.text to each attribute in each entity? how to distinguish the textfields?....i don´t think that the IF statment is the best approach ( it would be a LOT!!), and the other problem is the cells are dynamic ( so the user can add more kind of trousers for example)...
Any ideas would be most appreciate... i´m really stuck!.
Thanks in advance.
I´ve been reading a little, but i´m having trouble understanding something: When you say "you can set an object for each cell" are your referring to the classes that core data automatically creates for each entity(when you hit subclass NSmanageobject button),and then i should bind the texfields from each cell to an object of each entity class??.I already have the classes that are referring to each cell, and then i think i should be doing this: Trousers *trouse = [NSEntityDescription insertNewObjectForEntityForName:#"Trousers" inManagedObjectContext:self.managedObjectContext]; trouse.nameProduct =Textfield.text.and this is the part i don´t no the best approach, because i have more than one textfield in each cell(and i din´t make them property´s of my view) and doing like this, it will be an enourmous amount of work! Can you help me understand better?.
If you are using CoreData with a table view you should be hooking up model objects to the UI using NSFetchedResultsController
Have a look at the documentation and examples for this. It's designed to make this sort of thing less painful.

How to get NSFetchedResultsController to return relationships as sections for UITableViewController

I have a NSManagedObjectEntity 'Event' which has date and location attributes and one-to-many relationships: alerts, reminders, goals.
How do I setup an NSFetchedResultsController so that i can display this in a UITableView. Specifically, using the grouped dynamic table view with section headings:
Section 0 - list date and location
Section 1 - List all alerts
Section 2 - List all reminders
Section 3 - List all goals
I can return all the objects, but then I have to manually manage sections. Is there a way, maybe for the sectionNameKeyPath of the NSFetchedResultsController to dynamically generate these sections containing the set of objects for each section so that I can use the methods from the documentation such as the [[self.fetchedResultsController sections] count] method?
Thanks in advance
You can't use an NSFetchedResultsController's sections like that. You will have to write custom logic.

to-many without insertNewObjectForEntityForName

I have two NSManagedObjects. Both are based off of a selection inside a UITableView.
NSManagedObjects *One = [rootViewController.fetchedResultsController objectAtIndexPath:currentSelection];
NSManagedObjects *Two = [fetchedResultsController objectAtIndexPath:indexPath];
I want to link the two together (to-many), but since the entries already exist, I do not want to use insertNewObjectForEntityForName. If I use insertNewObjectForEntityForName my code works but it links the new entry to an existing entry. I need to link two already existing entries together.
Is this possible and if so, how would you go about it?
Solution found. One must use the same NSManagedObjectContext for both NSManagedObjects. Once I had done so, code worked as expected.

iphone SDK: Core Data, how to sort sections in an NSFetchedResultsController?

I have a core data app that is using the sectionNameKeyPath "group.name" with the fetchRequest in order to group the results by the group entity's name attribute. I'm grouping by group.name but I'd like to sort the sections by something other than group.name. According to the NSFetchedResultsController docs:
If the controller generates sections,
the first sort descriptor in the array
is used to group the objects into
sections; its key must either be the
same as sectionNameKeyPath or the
relative ordering using its key must
match that using sectionNameKeyPath.
Which means that the sections must be sorted in the same order the are grouped in. Despite the documentation, prior to iOS 4.2 you could get away without specifying the sectionNameKeyPath as the first sort descriptor which allowed you to sort the sections, but no longer.
What is the best way to sort sections in an NSFetechedResultsController? For example, I want my sections to be grouped by "group.name" but sorted by "group.timestamp".
From the NSFetchedResultsController docs:
You create a subclass of this class if
you want to customize the creation of
sections and index titles. You
override
sectionIndexTitleForSectionName: if
you want the section index title to be
something other than the capitalized
first letter of the section name. You
override sectionIndexTitles if you
want the index titles to be something
other than the array created by
calling
sectionIndexTitleForSectionName: on
all the known sections.

Core Data Document-based application: How do I model and control a entity that is instantiated only once per document?

I've got a few questions I've been trying to answer for myself (by hunting through the documentation) but I have a feeling I'm missing something.
Any hints (and/or pointers to appropriate documentation) would be much appreciated.
I'm building a Core Data document-based application. There are essentially two entities:
There is a single "Comparison" record associated with each document.
There are potentially many "Node" records associated with each document.
My first question is whether I'm thinking about this correctly. Since there is only a single Comparison object for each document, the attributes of the Comparison are essentially attributes of the Document itself. What (if any) is the preferred way of modeling that?
If a Comparison entity is in fact the right way to go, my next question is how and when to actually instantiate the (single) Comparison object. The user should not have to explicitly "add" the Comparison since there's going to be only one of them associated with the Document. Instead, a single Comparison object should be instantiated and inserted into the managedObjectContext. I've got something like this working already, with code in MyDocument.m that looks like this:
(void)windowControllerDidLoadNib:(NSWindowController *)windowController {
[super windowControllerDidLoadNib:windowController];
[NSEntityDescription insertNewObjectForEntityForName:#"Comparison" inManagedObjectContext:managedObjectContext];
}
However -- if the user creates a new document but then never does any work with it -- for example if he immediately clicks the close button -- then he should not be asked to "Save" the document. He should be asked to save his work only if he's actually entered any information. Is there a preferred way to implement this behavior?
I found this thread while struggling with the exact same issue. I have a table of Entity_A working in my document based Core Data app, but I need to figure out how to handle a required single-instance per document of Entity_B.
I've found something that seems to work. There's probably a better way, but this is getting me past this hurdle for now.
When the document's xib is loaded I simply check to see if an Entity_B has been created. if not, I create one and initialize its attributes.
- (void)windowControllerDidLoadNib:(NSWindowController *)aController
{
[super windowControllerDidLoadNib:aController];
//has an Entity_B been created? if not, create one.
NSError *theError = nil;
NSUInteger count = [[self managedObjectContext] countForFetchRequest:[NSFetchRequest fetchRequestWithEntityName:#"Entity_B"] error:&theError];
if( count == 0 )
{
NSManagedObject *newEntity_B = [NSEntityDescription insertNewObjectForEntityForName:#"Entity_B" inManagedObjectContext:[self managedObjectContext]];
[newEntity_B setValue:[NSNumber numberWithBool:YES] forKey:#"boolAttribute"];
[newEntity_B setValue:[NSNumber numberWithInt:2] forKey:#"intAttribute"];
}
}
I didn't insert that code snippet into the original post correctly. Trying again:
-(void)windowControllerDidLoadNib:(NSWindowController *)windowController {
[super windowControllerDidLoadNib:windowController];
[NSEntityDescription insertNewObjectForEntityForName:#"Comparison" inManagedObjectContext:managedObjectContext];
}
Your question about modelling is not very clear, can you please elaborate on what your "Comparison" entity is supposed to do and what sort of attributes you are assigning to it? It would be handy to see your "Document" entity structure so we can provide some useful input.
With regards to your second question, you could check if your NSManagedObject has been updated before deciding on whether to prompt the user to save their document or not:
if ([documentObject isUpdated]) {
...
}
More details in the documentation here http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/CoreDataFramework/Classes/NSManagedObject_Class/Reference/NSManagedObject.html#//apple_ref/occ/cl/NSManagedObject
Cheers,
Rog
There isn't really a "Document" entity, I was simply using that term to refer to the overall document that is saved when the user invokes the Save menu item. Perhaps there is a better way to refer to this concept? NSPersistentDocument?
Backing up a bit... the central idea of the application is to compare two hierarchical directory structures (a visual recursive "diff").
For now the "Comparison" entity has two string attributes, pathA and pathB, which are the names of the two directories to be compared. Each "Node" entity represents the name of a file down in the directory trees that are being compared. The Node entity contains at least one attribute ("relativePath") which is the path relative to the starting point specified in the Comparison.
My first question was simply whether it makes sense for there to be a "Comparison" entity since there is going to be only one of them instantiated (at some point after the user invokes the "New" menu item).
The second question is really at what point should the single "Comparison" object be instantiated and inserted into the managedObjectContext, i.e. what method is most appropriate to make this happen?
Finally if a "Comparison" object is automatically instantiated (at awakeFromNib time, perhaps?) but the user decides not to proceed, and simply clicks the close button, he should not be prompted to save (right?) What would be the appropriate way to accomplish this? The documentObject will appear to have been updated, because an "empty" Comparison object has in fact already been inserted automatically at startup, but the user has not modified it.
Hope that's clear... thanks.

Resources