views:

54

answers:

2

Hello everyone,

Im trying to create a listing app that is core data backed.The first page lets you create as many list as you want and name them. By tapping on a name in the first view, you will be taken to that actual list where you can create the items in that list. However if I create 3 lists they each have the same data. Do I need a different store with each first view cell? Also if I do how do I make it create a new store with every new cell that is added? Thanks for any help.!

alt text

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

//This is the second view that holds the list items
RootViewController *secondViewController = [[RootViewController alloc] initWithNibName:@"RootViewController" bundle:nil];

secondViewController.managedObjectContext = [self managedObjectContext];

[self.navigationController pushViewController:secondViewController animated:YES];
[secondViewController release];

}

Rootview.m

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [[fetchedResultsController sections] count];
}


// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

id <NSFetchedResultsSectionInfo> sectionInfo = [[fetchedResultsController sections] objectAtIndex:section];
return [sectionInfo numberOfObjects];
}


// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

static NSString *CellIdentifier = @"Cell";

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}

// Configure the cell.
[self configureCell:cell atIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;

return cell;
}


- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {

// Configure the cell to show the book's title
Book *book = [fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = book.title;
}


- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
// Display the authors' names as section headings.
return nil;
}


- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {

if (editingStyle == UITableViewCellEditingStyleDelete) {

    // Delete the managed object.
    NSManagedObjectContext *context = [fetchedResultsController managedObjectContext];
    [context deleteObject:[fetchedResultsController objectAtIndexPath:indexPath]];

    NSError *error;
    if (![context save:&error]) {
        // Update to handle the error appropriately.
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        exit(-1);  // Fail
    }
}   
}
+2  A: 

No you definitely do not need a separate store for each cell added.

You need a Datamodel which fits your requirements. List ----- ListEntry.

The first page shows all "List" entities, after selecting a list, all "ListEntries" with a relation to "List" are displayed.

Martin Brugger
Yes I just added another entity solely for the list items. My problem is that all list now have the same items. Such that I create a list and name it "A" I then add "apple" in list "A". I then create list "B" "apple" is inside list "B" as well. How can I fix this?
Tanner
@Tanner - Use a one-to-many or many-to-many relationship between List and ListEntry, then filter your fetch request as you drill down into a list to only display items that belong to the list being displayed.
Brad Larson
So for the entity ListItems, have an attribute of NSString called items. How would I filter this with each list is the part I dont understand though. Thanks
Tanner
Please post a screenshot of your datamodel, this would make helping a lot easier.
Martin Brugger
Full image can be found at http://www.tckdeveloper.com/Tutorials/iPhone/Screen%20shot%202010-07-07%20at%208.11.52%20AM.png Im using core data books as a starting place. The first set of code (didSelectRow) is from The first view that allows you to create the lists and name them. Selecting a list will take you to the rootView which is the code ive posted.
Tanner
+2  A: 

You design a data model based not on how the data will be displayed but instead on how the data logically relates to itself. Each entity should model a real world object, event or condition with no regard to how that data will end up being displayed.

In this case, you are modeling books and a user supplied organization of those books into list. You need a book entity to model the books and a list entity to model the users organization. (It doesn't have to be a "list" it could be "collection", "shelf" etc depending on what you're trying to model.)

Presumably, each book can be in different list and each list may contain many books.

Book {
    author:string;
    copyright:sting/date;
    item:(?);
    title:sting;
    list<<-(optional,nullify)-->>list.books
}

List {
    name:string;
    books<<--(optional,nullify)-->>book.list;
}

In your UI, you would have the fetched results controller (FRC) fetch all list entities and then display the name of each in a table view. When a table row is selected, you push the next view and hand it the NSSet returned by list.books of the list object associated with that row.

In the next table view, each row is populated from one or more attributes of each book entity in the passed set. When row is selected, you push a book detail view and pass it the book entity associated with the selected row.

Notice that from the perspective of the data model, the UI is irrelevant. You could be displaying the data in web view or even a text based command line. All the data model cares about are the contents of the entities and the logical relationships between them.

Design your data model to handle the logical relationships in your data. Once you do that, the UI becomes very simple to implement regardless of the format because the UI is not responsible for maintaining the integrity of the data model and the data model does not have to worry about the state of the UI.

TechZen
Thank you very much. I would give an arrow up if I had enough rep. The code provided, this is the actual data model correct? Meaning that I dont have to add this code anywhere? Also I understand the logic now but how could I filter each lists items when I dont know what the user will name a list and I dont know how much items the user will put in the different list. Thank you for your help so far.
Tanner
It's not code. It's just a textual way of representing an entity graph. Each list object represents a separate list and maintains its own custom set of related book objects. You have the user name the list when you create it and have the user add the books he wants to the list. When the user selects a list, bam, you have all the books in the list right in the chosen list object.
TechZen
Don't confuse entities and managed objects. Entities are akin to classes i.e. they define attributes and relationships but do not themselves hold data or logic. It is the individual instances of managed objects that hold data and logic. The entity graph/model tells the context how the managed objects relate to each other. Even though you have just two entities, that can translate into a functionally infinite number of managed objects at runtime. So you can have an vast number of list objects each containing its own set of book objects.
TechZen
Ive never dealt with NSSets so I apologize for the ignorance. Do I create different managed objects for each different list? Such as list "A" managedObject "A" list "B" managedObject "B"? Sorry im still a bit confused.
Tanner
Yes, exactly. Each list is represented by its own object. That can either be an instance of the generic NSManagedObject or you can create a dedicated NSManagedObject subclass called "list" (the name is actually arbitrary as long as you tell the model what it is.) As well, each book as its own object/instance as well. Core Data manages all these objects for you. You just have to tell Core Data to create them by inserting and to fetch them for you. Everything else (memory, relationship, disk access etc) is automatic.
TechZen
Don't make the mistake of thinking of Core Data as a non-object oriented SQL type database. Entities are not tables, attributes are not columns and objects are not rows. Core Data manages objects. Any SQL/table like stuff is (1) optional and (2) happens way behind the scenes.
TechZen
Thank you for the reply. Ive set up my model class like you said. What I dont yet understand is when A new list is created and its cell is tapped the process doesnt create anew managed context unique to this list. Do you know of any code that can create a new managed context with each new cell that is clicked?
Tanner
@Tanner - You don't want to create a new managed object context for each drill-down item. Generally, there should only be one managed object context for your entire application and it is passed down to the new fetched results controller used in each new view. If it helps, I walk through this in the video for the Core Data class from my iPhone course: http://deimos.apple.com/WebObjects/Core.woa/Browse/matcmadison.edu.3989485784.03989485786
Brad Larson
Thanks Brad. So its a new fetchedresultscontroller with each new view. Thanks for the help ill go watch now.
Tanner