Take the 2-minute tour ×

I can successfully update my sqlite database however I would like the primary key to correspond to the row selected in tableview. The reason I'm struggling is because I need to get the indexpath from the tableview and pass it to my Todo class where I update the database. Here's the code:

Tableview (RootViewController):

- (void)updateStatus:(id)sender { // called when a user presses the button to alter the status

NSIndexPath *indexPath = [self.tableView indexPathForCell:(UITableViewCell *)[sender superview]];
NSLog(@"The row id is %d",  indexPath.row); // This works

todoAppDelegate *appDelegate = (todoAppDelegate *)[[UIApplication sharedApplication] delegate];
Todo *td = [appDelegate.todos objectAtIndex:indexPath.row];

self.selectedIndexPath = indexPath;
NSLog(@"Selected index path is %i", self.selectedIndexPath); 

if (td.status == 0) {       
    [td updateStatus:1];
    NSLog(@"Status is %i",td.status);
else {
    [td updateStatus:0];

[appDelegate.todos makeObjectsPerformSelector:@selector(dehydrate)];

Todo class:

- (void) dehydrate {
if (dirty) { // If the todo is “dirty” meaning the dirty property was set to YES, we will need to save the new data to the database.
if (dehydrate_statment == nil) {
    const char *sql = "update todo set complete = ? where pk= ?"; // PK needs to correspond to indexpath in RootViewController

    if (sqlite3_prepare_v2(database, sql, -1, &dehydrate_statment, NULL) != SQLITE_OK) {
        NSAssert1(0, @"Error: failed to prepare statement with message '%s'.", sqlite3_errmsg(database));

sqlite3_bind_int(dehydrate_statment, 2, self.primaryKey);
sqlite3_bind_int(dehydrate_statment, 1, self.status);
int success = sqlite3_step(dehydrate_statment);

if (success != SQLITE_DONE) {
    NSAssert1(0, @"Error: failed to save priority with message '%s'.", sqlite3_errmsg(database));
dirty = NO;
NSLog(@"Dehydrate called");

Many thanks!!!

share|improve this question
too much code = long & complex question that only a few people will read... –  Vincent Guerci Apr 15 '11 at 19:08
Thanks for your help. –  medley Apr 15 '11 at 19:54

2 Answers 2

I have to assume from your code that each of the todo's will get the same PK (the indexPath.row).

Break your 'performSelector' apart, and pass each todo the index, like this:

  for ( Todo *todo in appDelegate.todos ) {
        [todo dehydrate:indexPath.row];

And re-declare dehydrate as:

     - (void) dehydrate:(int) primaryKey {  // use pk here ... }
share|improve this answer
Each of the todo's need to update the PK with the corresponding indexpath.row if that makes sense? Just not sure how to connect it all together, i.e. getting the indexpath.row or tag from the Rootview into the update method in the Todo class! Thanks. –  medley Apr 15 '11 at 20:03
I have tried this but it crashes with reason: '-[Todo dehydrate:]: unrecognized selector sent to instance. –  medley Apr 16 '11 at 12:45
"unrecognized selector" means you're calling a method with a different signature than the signature the method is declared with (or not declared at all). Are you passing dehydrate an int? Is the method signature declared with an int in the .h file? –  Rayfleck Apr 16 '11 at 13:04
I wasn't passing it an int, however you suggested to do so above. Either way it crashes! .h is: @property (nonatomic, retain) Todo *todo; –  medley Apr 16 '11 at 23:17

Some remarks about your code :

  1. Instead of using AppDelegate to host global data, you should use a singleton class
  2. using [appDelegate.todos makeObjectsPerformSelector:@selector(dehydrate)]; is over complex looking at what you want to do. A dehydrate method targeting a todo by pk would be better.

About your question :

Your Cell should host primary key / todo data for allowing you to "link" them if there is no correspondance between indexPath row and pk.

One easy trick if you don't want make your own cell subclass, is to use cell tag property

share|improve this answer
Hi, thanks for the suggestions. I agree with you regarding complexity, however this was a tutorial that I am extending and I'm unsure how to make it less complex. Regarding the tagging, I have: [accessoryButton setTag:indexPath.row]; but I am not sure how to retrieve it. Thanks again. –  medley Apr 16 '11 at 12:43
looking at your questions and comments, maybe you should start with some easier examples... you might retrieve your tag from sender.tag... –  Vincent Guerci Apr 16 '11 at 12:46

Your Answer


