views:

327

answers:

1

Hello all, I have a list app where users hit the + button and enter in an item that they want to appear in the list and hit save. The table is saved with core data. The only problem is when the cell is taped I want a checkmark to be displayed. Ive enabled multiple selection with

UITableViewCell *thisCell = [tableView cellForRowAtIndexPath:indexPath]; 
if (thisCell.accessoryType == UITableViewCellAccessoryNone) {
    thisCell.accessoryType = UITableViewCellAccessoryCheckmark;  
} else {
    thisCell.accessoryType = UITableViewCellAccessoryNone;
} 
[tableView deselectRowAtIndexPath:indexPath animated:NO]; 

I would like the checkmarks to be persisted in the cell after the user exits. I have created an attribute in my entity called "checks" and gave it the type of boolean but I dont know how to make it where if you hit a row then a check appears and is persisted. Any help would be greatly appreciated. Thanks

+4  A: 

This is how I do it. One notable point: CoreData does not store booleans, so any property labeled "boolean" is actually of type NSNumber. You've got to remember to convert back and forth when dealing with CoreData and boolean values.

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    NSManagedObject *selectedObject = [self.fetchedResultsController objectAtIndexPath:indexPath];


    if ([[selectedObject valueForKey:@"isDone"] boolValue]) {
        [selectedObject setValue:[NSNumber numberWithBool:NO] forKey:@"isDone"];
    } else {
        [selectedObject setValue:[NSNumber numberWithBool:YES] forKey:@"isDone"];
    }
}

I have my UITableViewController set as the the delegate for the NSFetchedResultsController, so the changes I made to the managed objects in the query ^^^ will cause the following two methods to be run.

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
    [self.tableView reloadData];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *defaultCellIdentifier = @"Item";

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

    NSManagedObject *item = [[self fetchedResultsController] objectAtIndexPath:indexPath];
    cell.textLabel.text = [item valueForKey:@"name"];

    if ([[item valueForKey:@"checks"] boolValue]) {
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
    } else {
        cell.accessoryType = UITableViewCellAccessoryNone;
    }

    cell.selectionStyle = UITableViewCellSelectionStyleNone;

    return cell;
}

Here's how everything ties together

  1. User clicks on a row
  2. tableView:didSelectRow... method changes the "isDone" property of the appropriate managed object.
  3. the fetched results controller notices that a managed object has changed and calls the controllerDidChangeContent method on its delegate.
  4. My controllerDidChangeContent method just reloads all the data in the table view
  5. When the tableView is reloaded, my tableView:cellForRow... method checks the "isDone" property of the managed item to see if the cell should have a checkmark or not.

And just so you don't get confused, I initially used a generic NSMangagedObject to store row state, which is why the first method I posted says, [selectedObject valueForKey:@"isDone"]. Later I switched to a subclassed managed object named JKItem, which is why the second set of methods is able to use item.isDone without generating a compiler warning.

kubi
Thank you for your reply. I have a question however would this tie the boolean to the attribute in my entity named "check"? Also would using NSUserDefaults be better to do this. Remember I also need a check mark to appear. Thanks
Tanner
your "check" property is my "isDone" property. With regards to using NSUserDefaults vs. CoreData, the answer is, it depends. NSUserDefaults is much much easier to set up, but CoreData is much more powerful. If you're only storing a handfull of values, I'd definitely use the defaults. If you're storing a huge number of values or you want to be able to easily slice and dice values or you want to update your data in the background and receive notification in the foreground, then CoreData is the way to go.
kubi
Hello, I tried the newly added code it gave me an error with JKItem so I changed that to check but then it said that check was undeclared. I couldnt just mute out the sentence because then item wouldnt be declared for the BOOl. Any ideas? I just need the checkmark to be saved using whatever means can save it fast and without hassle. Thanks
Tanner
JKItem gives you an error because you don't have a class named JKItem. If you aren't subclassing NSManagedObject then you need to use `[item setValue:[NSNumber numberWithBool:YES] forKey:@"check"];` instead of a property like I did.
kubi
It's worth reading through the Core Data accessors http://developer.apple.com/Mac/library/documentation/Cocoa/Conceptual/CoreData/Articles/cdAccessorMethods.html#//apple_ref/doc/uid/TP40002154 page. Long, complex, but very worthwhile to learn.
kubi
It tells me item undeclared. Is there a way to declare it where it works with my table?
Tanner
Ill read it but am I not just trying to access the attribute "check" and tell it yes or no? Its stating that item is undeclared. Do I put item there or something else?
Tanner
Are you sure you're using Core Data to store the date behind your table view? You should be pulling managed objects out of your context all over your table view controller, do it the same way here as you do it elsewhere.
kubi
Yes im 100% its core data but what im not sure of is how to connect the "check" attribute to the cells so that when I click a row it checks it and tells "check" that the boolean is YES.
Tanner
I edited my `cellForRowAtIndexPath` method for you.
kubi
Core data seems a bit over kill for just saving a check mark does it not? I would like to use NSUSerDefaults but where would I get a key for the checkmark? Could you please post code for that? Any help is appreciated. Thanks
Tanner
THANK you. However it says check is not in a structure or union. This is the only error. Would you like me to post my code?
Tanner
Ok ive removed my code and replaced it with yours exactly. However I cant select a row, nothing happend it doesnt turn blue or anything.
Tanner
I reset the simulator and set the entity default value to undecided and it worked. Thank you very much your a god!!!
Tanner