Sorry I'm pretty new to iOS dev.
I have a UITableView
setup from cells being pulled from a single XiB nib. I've created a on/off switch in the nib, and I am trying to save the state of the switch upon viewWillDisappear
for the number of cells that I have. (6 cells to be exact).
How can I loop through all the cells and save this information?
I tried this in my UIViewController to get the info for one cell:
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
UITableView *tv = (UITableView *)self.view;
UITableViewCell *tvc = [tv cellForRowAtIndexPath:0];
}
it gives me the error "Program received signal: "EXC_BAD_INSTRUCTION".
How can I accomplish this?
You have to pass a valid NSIndexPath
to cellForRowAtIndexPath:
. You used 0, which means no indexPath.
You should use something like this:
UITableViewCell *tvc = [tv cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
BUT. Don't do this. Don't save state in the UITableViewCell.
Update your dataSource when a switch changed its state.
If you have implemented the UITableViewDataSource methods the right why your tableView reuses cells. That means the state of your cells will vanish when the cells are reused.
Your approach might work for 6 cells. But it will fail for 9 cells.
It will probably even fail if you scroll the first cell off screen.
I wrote a quick demo (if you don't use ARC add release
where they are necessary) to show you how you should do it instead:
- (void)viewDidLoad
{
[super viewDidLoad];
self.dataSource = [NSMutableArray arrayWithCapacity:6];
for (NSInteger i = 0; i < 6; i++) {
[self.dataSource addObject:[NSNumber numberWithBool:YES]];
}
}
- (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];
UISwitch *aSwitch = [[UISwitch alloc] init];
[aSwitch addTarget:self action:@selector(switchChanged:) forControlEvents:UIControlEventValueChanged];
cell.accessoryView = aSwitch;
}
UISwitch *aSwitch = (UISwitch *)cell.accessoryView;
aSwitch.on = [[self.dataSource objectAtIndex:indexPath.row] boolValue];
/* configure cell */
return cell;
}
- (IBAction)switchChanged:(UISwitch *)sender
{
// UITableViewCell *cell = (UITableViewCell *)[sender superview];
// NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
CGPoint senderOriginInTableView = [sender convertPoint:CGPointZero toView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:senderOriginInTableView];
[self.dataSource replaceObjectAtIndex:indexPath.row withObject:[NSNumber numberWithBool:sender.on]];
}
as you see it's not very complicated to not store state in the cells :-)
Moving [super viewDidDisappear:animated];
to the end of your method may be the most expedient way to address the problem. If that does not work, move the logic into viewWillDisappear:animated:
.
A better way to deal with this would be to avoid reading the current state from the view at all. Rather, the view should pass the state to the model on each update. This way you would be able to harvest the current state from your model, entirely independently from the state of your view.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With