At canEditRowAtIndexPath Method, reloadData of UITableView not work properly?

In my application, I reload my TableView ([tablView reloadData];) after delete row from TableView then canEditRowAtIndexPath Method alway call for (pervious) total number Of Rows.

For Example:

If i have 5 Rows on my TableView, then i delete 1 row from tableView. After deleting, I reload my TableView ([tablView reloadData]) but canEditRowAtIndexPath Method calls 5 time instead of 4 times ??

So i always got Following Error:

Terminating app due to uncaught exception 'NSRangeException', reason: '* **-[__NSArrayM objectAtIndex:]: index 5 beyond bounds [0 .. 4]'

I also tried to reload table after some delay (using NSTimer) but it also not worked for me.

I put some code here:

I apply canEditRowAtIndexPath on specific row which @"status" isEqualToString:@"directory" such like,

- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSLog(@"%d", self.listOfSounds.count);
    // Return NO if you do not want the specified item to be editable.
    if([[[self.listOfSounds objectAtIndex:indexPath.row] objectForKey:@"status"] isEqualToString:@"directory"])
        return YES;
    else
        return NO;
}  

Code of delete row:

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{

    if (editingStyle == UITableViewCellEditingStyleDelete)
    {
        [self.sql_ deleteSoundFileAudioTableWhereMainID:[[self.listOfSounds objectAtIndex:indexPath.row] objectForKey:@"main_id"]]; /// delete record from DB
        [self.listOfSounds removeObjectAtIndex:indexPath.row]; /// delete record from Array
        [self updateListofSoundsFile]; /// Custom method
    }
}

- (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath
{
    return NO; // i also tried to  return YES;
}

Here updateListofSoundsFile is my custom method code is :

-(void)updateListofSoundsFile
{
    if(self.listOfSounds.count > 0)
        [self.listOfSounds removeAllObjects];

    self.listOfSounds = [self.sql_ getAllDataFromAudioTable]; // get all record from DB
    NSLog(@"%d",self.listOfSounds.count);

    [self.tblView reloadData];  
}

Please Give any suggestion, How can i solve this issue ? Thanks :)

Answers


you need to remove raw from tableview also befor remove item from array and reload data using this line becouse remove item from array but not tableview.

[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{

    if (editingStyle == UITableViewCellEditingStyleDelete)
    {
        [self.sql_ deleteSoundFileAudioTableWhereMainID:[[self.listOfSounds objectAtIndex:indexPath.row] objectForKey:@"main_id"]]; /// delete record from DB

        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
        [self.listOfSounds removeObjectAtIndex:indexPath.row]; /// delete record from Array

        [self updateListofSoundsFile]; /// Custom method
    }
}

I ran into this same problem. The issue was that I deleted the object of the cell but when I used the reloadData method of the tableView, my canEditRowAtIndexPath method was not being called resulting in being able to edit cells that I do not want edited. The true fix was not calling the deleteRowsAtIndexPaths method, but the [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; method.

Basically here is what was happening:

When I called reloadData: The raw data was not being removed from the tableView as Nitin said. Therefore this is not the solution.

When I called deleteRowsAtIndexPaths: iOS detected a discrepancy between the underlying data and the number of cells (because I had already removed the underlying object). The result was a crash which is also not the solution (obviously).

Now for The Fix!

When I called reloadRowsAtIndexPaths: This caused the tableView to simply reload that single cell AND it got rid of the raw data. This is the solution.

Rather than removing the dataSource object, then trying to remove the cell that is essentially backed by nothing at this point (which causes a crash), simply remove the dataSource object, then reload that indexPath of the tableView

Here is the general format of the method:

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (editingStyle == UITableViewCellEditingStyleDelete)
    {
        [myDataSourceArray removeObjectAtIndex:indexPath.row];
        [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
    }
}

This is the first time I ran into the issue with the residual raw data that is not removed by simply calling the reloadData method. This is certainly the most elegant solution that I have seen thus far.

Happy Coding! I hope this helps.


- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{

    if (editingStyle == UITableViewCellEditingStyleDelete)
    {
        [self.sql_ deleteSoundFileAudioTableWhereMainID:[[self.listOfSounds objectAtIndex:indexPath.row] objectForKey:@"main_id"]]; /// delete record from DB
        [self.listOfSounds removeObjectAtIndex:indexPath.row]; /// delete record from Array
        [self updateListofSoundsFile]; /// Custom method
    }
   [self.tblView reloadData]; 
}

When it comes to me, I analysed as below:

As commented by rmaddy on Nitin Gohel's answer:

  1. You should always remove the data from the data source before updating the table.

    I feels this is the ideal way.

  2. If you are going to call reloadData, there is no reason at all to first call deleteRowsAtIndexPath.

    This is also looks correct.

I analysed ambiguity, if I write reloadData its crashishing but once I write deleteRowsAtIndexPath it worked well.

Hope someone will emphasise on this issue for its causes etc.


Need Your Help

Democratic queue in Sidekiq

ruby-on-rails asynchronous redis sidekiq

Users can create a Project object that contain multiple tasks. When user tells the project to execute all those tasks are put on the default queue from Sidekiq.

Create Control in foreach loop?

c# winforms

There is string array contains some file location.

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.