I have a to-do list app with a bunch of tasks. Each task has a UITableViewCell. After each table view cell is tapped, it creates a view controller with the task at that row's index path's property. These view controllers are all stored in a NSDictionary. This is the code representation of what I just said:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
DetailViewController *detailVC;
if (![self.detailViewsDictionary.allKeys containsObject:indexPath]){
detailVC = [[DetailViewController alloc]initWithNibName:@"DetailViewController" bundle:nil];
[self.detailViewsDictionary setObject:detailVC forKey:indexPath];
detailVC.context = self.managedObjectContext;
}else{
detailVC = self.detailViewsDictionary[indexPath];
}
Tasks *task = [[self fetchedResultsController] objectAtIndexPath:indexPath];
detailVC.testTask = task;
[[self navigationController] pushViewController:detailVC animated:YES];
NSLog(@"%@", self.detailViewsDictionary);
}
So this method of creating unique view controllers and storing them with a certain key almost always works. The problem arises when I delete or move the view controllers:
I was under the impression that a cell's gets recycled as you scroll down (dequeue). This means that marking each cell with a number identifier would result in multiple cells for the same identifier.
Also, if you stored each view controller with a indexPath key, how do you make sure the key isn't set to two view controllers..? For example. Let's say you have 4 cells, which means 4 view controllers. You delete cell 3. Cell 4 moves down to cell 3s spot. You create a new cell which goes to spot 4. Now you have two controllers with the same indexPath key! How do you avoid this?? It's screwing up my app right now because tasks that have already been moved are loading their properties in the wrong view controller/cell!
I was suggested this to solve the problem before: "You maintain an NSMutableArray that "shadows" the contents of the table." I was also suggested to use tags. However, I don't understand what how to implement these.
edit: ---random string--- In tasks.m
-(NSString *)uniqueIdentifierString{
static NSString *alphabet = @"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXZY0123456789";
NSMutableString *s = [NSMutableString stringWithCapacity:20];
for (NSUInteger i = 0U; i < 20; i++) {
u_int32_t r = arc4random() % [alphabet length];
unichar c = [alphabet characterAtIndex:r];
[s appendFormat:@"%C", c];
}
return s;
}
In tableviewcontroller.m
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
DetailViewController *detailVC;
Tasks *task = [[self fetchedResultsController] objectAtIndexPath:indexPath];
if (![self.detailViewsDictionary.allKeys containsObject:task.uniqueIdentifierString]){
detailVC = [[DetailViewController alloc]initWithNibName:@"DetailViewController" bundle:nil];
[self.detailViewsDictionary setObject:detailVC forKey:task.uniqueIdentifierString];
detailVC.context = self.managedObjectContext;
}else{
detailVC = self.detailViewsDictionary[task.uniqueIdentifierString];
}
detailVC.testTask = task;
[[self navigationController] pushViewController:detailVC animated:YES];
NSLog(@"%@", detailVC);
NSLog(@"%@", task.uniqueIdentifierString);
}