3

I use asihttprequest to download a file but when the download fails, the cell associated with the file in the table doesn't remove from the tableview.

When I swipe to delete, I have this error :

* Terminating app due to uncaught exception 'NSRangeException', reason: '* -[NSMutableArray objectAtIndex:]: index 0 beyond bounds for empty array'

How can I remove the cell ?

MANAGER.h

NSMutableArray *contentArray;

MANAGER.m

- (id)initWithStyle:(UITableViewStyle)style {
if (self == [super initWithStyle:style]) {

     self.navigationController.navigationBar.tintColor = [UIColor blackColor];
    self.navigationItem.rightBarButtonItem = self.editButtonItem;
    contentArray = [[NSMutableArray alloc] init];
    progArray = [[NSMutableArray alloc] init];
    self.view.backgroundColor = [UIColor clearColor];

    //saveTo = [[NSUserDefaults standardUserDefaults] stringForKey:@"save_to"];

    AppDelegate_iPhone* delegate = (AppDelegate_iPhone *)[[UIApplication sharedApplication] delegate];
    if([delegate saveTo] != nil)
    {
        saveTo = [delegate saveTo];
    }

    if(saveTo == nil)
    {
        saveTo = @"/";
    }


    allFiles = [[NSMutableArray alloc] init];
    NSDirectoryEnumerator *dirEnum = [ [ NSFileManager defaultManager ] enumeratorAtPath:saveTo];
    NSString *file;
    while ((file = [ dirEnum nextObject ])) 
    {
        if(file != nil)
        {
            if([file rangeOfString:@".mp4" options: NSCaseInsensitiveSearch].length > 0 || [file rangeOfString:@".mov" options: NSCaseInsensitiveSearch].length > 0 || [file rangeOfString:@".m4v" options: NSCaseInsensitiveSearch].length > 0 || [file rangeOfString:@".pdf" options: NSCaseInsensitiveSearch].length > 0 )

            {
                [ allFiles addObject: file];
            }
        }
    }
}
return self;
}

    // Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {

    if(indexPath.section == 0)
    {

        if (editingStyle == UITableViewCellEditingStyleDelete) 
        {
            Selected = indexPath.row;
            //Remove The Temporary File
            NSFileManager *fileManager = [NSFileManager defaultManager];
            if([fileManager fileExistsAtPath:[(ASIHTTPRequest *)[contentArray objectAtIndex:indexPath.row] temporaryFileDownloadPath]])
            {
......


- (void)requestFailed:(ASIHTTPRequest *)request
    {

        [contentArray removeObject:request];
        [progArray removeObject:request];
        [self reloadMyData];
       [self.tableView reloadData];
    }

-(void)reloadMyData
{
    allFiles = [[NSMutableArray alloc] init];
    AppDelegate_iPhone* delegate = (AppDelegate_iPhone *)[[UIApplication sharedApplication] delegate];
    if([delegate saveTo] != nil)
    {
        saveTo = [delegate saveTo];
    }

    NSDirectoryEnumerator *dirEnum = [ [ NSFileManager defaultManager ] enumeratorAtPath:saveTo];
    NSString *file;
    while ((file = [ dirEnum nextObject ])) 
    {
        if(file != nil)
        {
            //if([file rangeOfString:@".mp4" options: NSCaseInsensitiveSearch].length > 0 || [file rangeOfString:@".mov" options: NSCaseInsensitiveSearch].length > 0 || [file rangeOfString:@".mp3" options: NSCaseInsensitiveSearch].length > 0 )
            if([file rangeOfString:@".mp4" options: NSCaseInsensitiveSearch].length > 0 || [file rangeOfString:@".mov" options: NSCaseInsensitiveSearch].length > 0 || [file rangeOfString:@".m4v" options: NSCaseInsensitiveSearch].length > 0 || [file rangeOfString:@".pdf" options: NSCaseInsensitiveSearch].length > 0)
            {
                [ allFiles addObject: file];
            }
        }
    }


}



#pragma mark -
#pragma mark Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)aTableView {
    // Return the number of sections.
    return 2;
}


- (NSInteger)tableView:(UITableView *)aTableView numberOfRowsInSection:(NSInteger)section {
    // Return the number of rows in the section.
    if(section == 0)
    {
        return [progArray count];
    }
    else {
        return [allFiles count];
    }
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    NSString *CellIdentifier = [NSString stringWithFormat:@"CellIdentifier_%i_%i",indexPath.section,indexPath.row];
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    cell = nil;

    if(indexPath.section == 0)
    {
        if (cell == nil) {
            cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
            cell.accessoryType = UITableViewCellAccessoryNone;
            cell.selectionStyle = UITableViewCellSelectionStyleNone;
        }
        [cell addSubview:[progArray objectAtIndex:indexPath.row]];
    }
    else {
        if (cell == nil) {
            cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
        }
       // cell.accessoryType = UITableViewCellAccessoryNone;
        cell.selectionStyle = UITableViewCellSelectionStyleBlue;
        cell.textLabel.text = [allFiles objectAtIndex:indexPath.row];
    }


    return cell;
}
Alby
  • 273
  • 6
  • 14
  • sounds like your datasource is missing the object you'r trying to remove – JoBu1324 Jul 12 '11 at 01:01
  • The downloads fails the object is removed [contentArray removeObject:request]; but not the cell... Then when I swipe to delete and delete the cell I have the error because the object was already removed.. How can I remove the cell immediately after the download fails ? – Alby Jul 12 '11 at 01:13
  • Does the app crash if you don't remove the object when the download fails? If not, when you perform a swipe to delete and delete the cell, is the object removed properly? – JoBu1324 Jul 12 '11 at 04:37
  • No the app doesn't crash when I don't remove the object. Then the swipe to delete work properly and it deletes the cell with the object properly – Alby Jul 12 '11 at 05:12
  • Glad I could help - I posted an answer explaining what happened, please accept it so I can get credit for helping you! – JoBu1324 Jul 12 '11 at 07:34
  • for future users: see this too if it helps.. http://stackoverflow.com/a/31579030/884674 – jeet.chanchawat Jul 23 '15 at 05:47

1 Answers1

5

When deleting a row from a tableView, you need to remove the object from the datasource at the same time you delete the row. If you delete a row from the datasource, you need to update the table (-deleteRowsAtIndexPaths:withRowAnimation:) at the time of deletion to maintain the relationship between the tableView and the datasource.

JoBu1324
  • 7,751
  • 6
  • 44
  • 61
  • How do I do that when there are 5 objects in the indexpath and the third one (for example) needs to be deleted after the download fails? – Alby Jul 12 '11 at 14:25
  • Any chance to remove the row of the associated REQUEST without the need of user interaction ? – Alby Jul 13 '11 at 04:12
  • Yes, although the method I mentioned above was from memory, and it wasn't quite right. To remove the row without user interaction, you will need to send the -deleteRowsAtIndexPaths:withRowAnimation: message to the tableView *after* deleting the row from your data source. Here's an example: [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:row inSection:section]] withRowAnimation:YES]. – JoBu1324 Jul 13 '11 at 08:01
  • And what will be the row and the section of the REQUEST ? – Alby Jul 13 '11 at 11:39
  • I would need to see a) the code that performs the deletion of the request and b) the code that sets up your tableView from your dataSource. The bottom line is that you need to calculate which row is getting deleted when you delete your request, and get your indexPath from that. – JoBu1324 Jul 13 '11 at 16:50
  • I edited the code in the question. Could you help me with theses codes or do you need something else ? – Alby Jul 13 '11 at 17:02
  • 1
    Wouldn't the section be 0, since progArray is populating that section? The row would be [progArray indexOfObject:request] – JoBu1324 Jul 13 '11 at 17:12
  • so using - (void)requestFailed:(ASIHTTPRequest *)request { [self.tableView deleteRowAtIndexPath:[NSIndexPath indexPathForRow:[progArray indexOfObject:request] inSection:0]]; } leads to error: -[UITableView deleteRowAtIndexPath:]: unrecognized selector sent to instance 0x6833800 2011-07-13 13:20:47.150 Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UITableView deleteRowAtIndexPath:]: unrecognized selector sent to instance 0x6833800' – Alby Jul 13 '11 at 17:36
  • That will happen, because I mistyped the message selector in one of my comments. You need -deleteRowsAtIndexPaths:withRowAnimation: instead of -deleteRowAtIndexPath: – JoBu1324 Jul 13 '11 at 17:37
  • @Alby let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/1421/discussion-between-jobu1324-and-alby) – JoBu1324 Jul 13 '11 at 17:37