EvilAegis
EvilAegis

Reputation: 733

having error with custom checkboxes in uitableview cells

im getting the error: * Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'attempt to insert row 0 into section 0, but there are only 0 rows in section 0 after the update'*

I have 2 sections and I am trying to make it so when you click the checkbox of a cell in one of the sections, it goes to the other section (ex: section 1->section 2)

here is some relevant code of mine:

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
   UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"UITableViewCell"];
    if (!cell)
        cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"UITableViewCell"];
    if([indexPath section] == 0){
    cell.textLabel.text = [[[taskArray objectAtIndex:[indexPath row]] taskName] uppercaseString];
    cell.imageView.image = [UIImage imageNamed:@"checkboxtry2.png"];
    } else if ([indexPath section] == 1) {
    cell.textLabel.text = [[[completedArray objectAtIndex:[indexPath row]] taskName] uppercaseString];
     cell.imageView.image = [UIImage imageNamed:@"checkboxtry2selected.png"];
    }

    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(handlechecking:)];
    [cell.imageView addGestureRecognizer:tap];
    cell.imageView.userInteractionEnabled = YES;
    return cell;
}
-(void)handlechecking:(UITapGestureRecognizer *)t{
        CGPoint tapLocation = [t locationInView:self.tableView];
        NSIndexPath *tappedIndexPath = [self.tableView indexPathForRowAtPoint:tapLocation];

        if (tappedIndexPath.section == 0) {
            [completedArray addObject:[taskArray objectAtIndex:tappedIndexPath.row]];
            [taskArray removeObject:[taskArray objectAtIndex:tappedIndexPath.row]];
        }
        else {
            [taskArray addObject:[completedArray objectAtIndex:tappedIndexPath.row]];
            [completedArray removeObject:[completedArray objectAtIndex:tappedIndexPath.row]];
        }
        [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:tappedIndexPath] withRowAnimation: UITableViewRowAnimationFade];
}

I have two arrays: taskArray which handles objects in section 0 and completedArray which handles objects in section 1.

---EDIT--- Here is what I have now: TableViewController.h

@interface ToDoTableViewController : UITableViewController <Properties2ViewControllerDelegate, UITableViewDelegate, SettingsViewControllerDelegate>
@property (strong, nonatomic) NSMutableArray *taskArray;
@property (strong, nonatomic) NSMutableArray *completedArray;
@property (strong, nonatomic) NSMutableArray *holdViewsArray;
-(IBAction)addCell:(id)sender;
-(void)buttonPressed:(id)sender;
-(void)handlechecking:(UITapGestureRecognizer *)t;

TableViewController.m

-(void) viewDidLoad{
    [self.tableView setDelegate:self];
    [self setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];

    taskArray = [[NSMutableArray alloc] init];
    completedArray = [[NSMutableArray alloc]init];
    holdViewsArray = [[NSMutableArray alloc]init];
   }
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
   UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"UITableViewCell"];
    if (!cell)
        cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"UITableViewCell"];
    NSString *detailText = [NSString stringWithFormat:@"%.0f", [[taskArray objectAtIndex:[indexPath row]] timeInterval]];
    [cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
    [cell setBackgroundColor:[UIColor colorWithRed:236.0/255 green:240.0/255 blue:241.0/255 alpha:1.0f]];
    cell.textLabel.textColor = baseColor;
    [[cell detailTextLabel] setText:detailText];
    [[cell detailTextLabel] setFont:[UIFont fontWithName:@"Avenir-Black" size:12]];
    [[cell textLabel] setFont:[UIFont fontWithName:@"AvenirNext-DemiBold" size:16]];

    if([indexPath section] == 0){
    cell.textLabel.text = [[[taskArray objectAtIndex:[indexPath row]] taskName] uppercaseString];
    cell.imageView.image = [UIImage imageNamed:@"unchecked.png"];
    } else if ([indexPath section] == 1) {
    cell.textLabel.text = [[[completedArray objectAtIndex:[indexPath row]] taskName] uppercaseString];
     cell.imageView.image = [UIImage imageNamed:@"checked.png"];
    }

    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(handlechecking:)];
    [cell.imageView addGestureRecognizer:tap];
    cell.imageView.userInteractionEnabled = YES;
    return cell;

}
-(void)handlechecking:(UITapGestureRecognizer *)t{

        CGPoint tapLocation = [t locationInView:self.tableView];
        NSIndexPath *tappedIndexPath = [self.tableView indexPathForRowAtPoint:tapLocation];
        NSIndexPath *newIndexPath = nil;

        if (tappedIndexPath.section == 0) {

            NSUInteger newRowIndex = self.completedArray.count;
            [self.completedArray addObject:[self.taskArray objectAtIndex:tappedIndexPath.row]];
            [self.taskArray removeObject:[self.taskArray objectAtIndex:tappedIndexPath.row]];
            newIndexPath = [NSIndexPath indexPathForRow:newRowIndex inSection:1];
        } else {

            NSUInteger newRowIndex = self.taskArray.count;
            [self.taskArray addObject:[self.completedArray objectAtIndex:tappedIndexPath.row]];
            [self.completedArray removeObject:[self.completedArray objectAtIndex:tappedIndexPath.row]];
            newIndexPath = [NSIndexPath indexPathForRow:newRowIndex inSection:0];
        }
        [self.tableView beginUpdates];
        [self.tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationNone];
        [self.tableView deleteRowsAtIndexPaths:@[tappedIndexPath] withRowAnimation:UITableViewRowAnimationNone];
        [self.tableView endUpdates];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    NSInteger num = 0;
    if (section == 0) {
        num = self.taskArray.count;
    } else {
        num = self.completedArray.count;
    }
    return num;
}


 -(void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath{
   Tasks *taskToMove = [taskArray objectAtIndex:[sourceIndexPath row]];
    if (sourceIndexPath.row > destinationIndexPath.row) {
        [taskArray insertObject:taskToMove atIndex:destinationIndexPath.row];
        [taskArray removeObjectAtIndex:(sourceIndexPath.row + 1)];
    }
    else if (sourceIndexPath.row < destinationIndexPath.row) {
        [taskArray insertObject:taskToMove atIndex:(destinationIndexPath.row + 1)];
        [taskArray removeObjectAtIndex:(sourceIndexPath.row)];
    }
}
-(IBAction)addCell:(id)sender{
    Properties2ViewController *pvc = [[Properties2ViewController alloc]init];
    [pvc setDelegate:self];
    [self presentViewController:pvc animated:YES completion:NULL];
    [pvc setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
}
-(void)properties2ViewControllerDidEnterPropertiesSuccesfully:(Tasks *)t{
    if (![[t taskName] isEqual: @""]) {
    [taskArray addObject:t];
    }
    [self.tableView reloadData];
}

Properties2ViewController.m

-(IBAction)dismiss:(id)sender{
    testTask = [[Tasks alloc]init];
    testTask.taskName = taskName.text;
    testTask.timeInterval = datePicker.countDownDuration;
    testTask.dateCreated = [NSDate date];
    if ([self.delegate respondsToSelector:@selector (properties2ViewControllerDidEnterPropertiesSuccesfully:)]){
        [self.delegate properties2ViewControllerDidEnterPropertiesSuccesfully:testTask];
    }
    [self dismissViewControllerAnimated:YES completion:NULL];
}

Properties2viewcontroller is a modal controller that adds a Task object to the taskArray.

Upvotes: 0

Views: 304

Answers (2)

Numeral
Numeral

Reputation: 1405

You are trying to reload rows but what you actually want to do is delete row from section 0 and add it to section 1 or vise versa. So in handlechecking method you must write something like this:

-(void)handlechecking:(UITapGestureRecognizer *)t{

CGPoint tapLocation = [t locationInView:self.tableView];
NSIndexPath *tappedIndexPath = [self.tableView indexPathForRowAtPoint:tapLocation];
NSIndexPath *newIndexPath = nil;

if (tappedIndexPath.section == 0) {

    NSUInteger newRowIndex = self.sectionTwoArr.count;
    [self.sectionTwoArr addObject:[self.sectionOneArr objectAtIndex:tappedIndexPath.row]];
    [self.sectionOneArr removeObject:[self.sectionOneArr objectAtIndex:tappedIndexPath.row]];
    newIndexPath = [NSIndexPath indexPathForRow:newRowindex inSection:1];
} else {

    NSUInteger newRowIndex = self.sectionOneArr.count;
    [self.sectionOneArr addObject:[self.sectionTwoArr objectAtIndex:tappedIndexPath.row]];
    [self.sectionTwoArr removeObject:[self.sectionTwoArr objectAtIndex:tappedIndexPath.row]];
    newIndexPath = [NSIndexPath indexPathForRow:newRowindex inSection:0];
}
[self.tableView beginUpdates];
[self.tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationNone];
[self.tableView deleteRowsAtIndexPaths:@[tappedIndexPath] withRowAnimation:UITableViewRowAnimationNone];
[self.tableView endUpdates];
}

Edit

Full implementation of other methods

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    self.sectionOneArr = [@[@"ololo", @"dsd", @"dsdfsf"] mutableCopy];
    self.sectionTwoArr = [@[@"ototo",@"dd", @"sdfsdfsd"] mutableCopy];
}


- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {

    return 2;
}


-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

    NSInteger num = 0;
    if (section == 0) {
        num = self.sectionOneArr.count;
    } else {
        num = self.sectionTwoArr.count;
    }
    return num;
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"UITableViewCell"];
    if (!cell)
        cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"UITableViewCell"];
    if([indexPath section] == 0){
        cell.textLabel.text = [[self.sectionOneArr objectAtIndex:[indexPath row]] uppercaseString];
        cell.imageView.image = [UIImage imageNamed:@"unchecked.jpeg"];
    } else if ([indexPath section] == 1) {
        cell.textLabel.text = [[self.sectionTwoArr objectAtIndex:[indexPath row]] uppercaseString];
        cell.imageView.image = [UIImage imageNamed:@"checked.jpeg"];
    }

    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(handlechecking:)];
    [cell.imageView addGestureRecognizer:tap];
    cell.imageView.userInteractionEnabled = YES;

    return cell;
}


- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {

    NSString * num = nil;
    if (section == 0) {
        num = @"One";
    } else {
        num = @"Two";
    }
    return num;
}

Upvotes: 1

JustAnotherCoder
JustAnotherCoder

Reputation: 2575

Your code looks correct but I would venture a guess that the problem is in your tableView:numberOfRowsInSection: method. Are you returning the proper count of rows for each section? Should look like this:

if([indexPath section] == 0){
   return [taskArray count];
} else {
   return [completeArray count];
}

Upvotes: 0

Related Questions