views:

1291

answers:

2

Okay I know I'm running up against my limits of understanding as regards objective-c, cocoa, xcode, and blah blah and so on. But here's what I'm trying to do:

I have a tableview in a viewcontroller. The tableview's delegate is the viewcontroller. Viewcontroller has an outlet to the tableview. The table is put together using custom cells (with IB xib) and data from an xml file. In the custom cell there are two buttons - and when the cell is created the button action is added as an addTarget to self (the viewcontroller) which then goes to an action. The viewcontroller button action method gets the row of the button pressed in the table and then changes the cell's text and the button's title.

But of course when I scroll that particular cell out of view and back into view it's been reset to the beginning state. I assume this has to do with cell dequeueing etc. Any ideas?

here's the relevant bits and code:

custom cell: has outlets to buttons and textlabel.

cell create code in the datasource cellForRowAtIndexPath... {

static NSString *dialogueCellIdentifier = @"dialogueCellIdentifier";

dialogue_cell *cell = (dialogue_cell *)[tableView dequeueReusableCellWithIdentifier:dialogueCellIdentifier];

if (cell == nil) {
 NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"dialogue_cell" owner:self options:nil];
 cell = [nib objectAtIndex:0];
    [[cell lButton] addTarget:self action:@selector(lButtonPressed:) forControlEvents:UIControlEventTouchUpInside];  
}

[[cell lButton] setTag:[indexPath row]];

NSString *row = [NSString stringWithFormat:@"%i",[indexPath row]]; 
NSString *en = [[self.dataArray objectForKey:row] valueForKey:@"en"];

cell.mainText.text = en;


return cell;
}

and the lButton method...

NSIndexPath *thisCellPath = [NSIndexPath indexPathForRow:[sender tag] inSection:0];
dialogue_cell *thisCell = (dialogue_cell *)[self.dialogueTable cellForRowAtIndexPath:thisCellPath];
NSString *row = [NSString stringWithFormat:@"%i",[sender tag]];
if ([thisCell.languageButton.currentTitle isEqualToString:@"en"]) {
 [thisCell.languageButton setTitle:@"zc" forState:UIControlStateNormal];
 thisCell.mainText.text = [[self.lineArray objectForKey:row] valueForKey:@"lineText_zc"];
} else {
 [thisCell.languageButton setTitle:@"en" forState:UIControlStateNormal];
 thisCell.mainText.text = [[self.lineArray objectForKey:row] valueForKey:@"lineText_en"];  
}

so two questions:
1. is there a way to make the cell retain what is in the label and button name even though it's scrolled offscreen?
2. is there a way to set the label and button name within the cell custom class instead of sending the button action to the viewcontroller that the table is in?

Thanks!

A: 

OK i had this problem too, took me awihle but I figure it out, the cell queue is they key here, when you are trying to get your cell back your are using this

NSIndexPath *thisCellPath = [NSIndexPath indexPathForRow:[sender tag] inSection:0];
dialogue_cell *thisCell = (dialogue_cell *)[self.dialogueTable cellForRowAtIndexPath:thisCellPath];

When the cell is off the view, the table view unloads this cell and instead you get a cell thats in the original state (or prolly nil) when you call this because its n ot longer part of the table view until the cells come back into the view screen.

What you have to do is since you a re enqueuing your cells, I am going to assume you are doing this correctly and you are giving a different name to each cell, instead of doing what you did above you must get your cell like so

cell=[tableView dequeueReusableCellWithIdentifier:dialogueCellIdentifier];

This will give you your cell with the state it was in when the user modified it...Hope this helps! As for your second question, you can just set the target to be the cell instead of the view controller, this will call that action inside your custom cells class..

Daniel
Thanks for the help - actually I made up my own scheme similar to what lostInTransit said above and it works great. Nothing quite like that feeling of solving a problem!
+1  A: 

It does not really have anything to do with the dequeueing of cells but the data you are displaying in the cellForRowAtIndexPath. Every time a cell is going to be displayed, this method is called.

I assume you are changing the language of the cell's text on button click. But every time the cell is redrawn you are redisplaying the english text. One way to "retain" the cell's state would be to create an array for the languages being used on each cell and based on the array's value for a particular row, populate the cell's text. You will just have to maintain the state of the cell in the array.

lostInTransit
You will just have to maintain the state of the cell in the array....No you dont look at my post
Daniel
Actually I came up with this solution on my own. It works quite well (though it does seem to make scrolling a little jerky it seems). Might try another strategy as my tables will rarely be longer than 15-20 cells.