tags:

views:

1358

answers:

2

Hi,

The Three20 is great library. It's making the work with tables very easy. But one gap that I noticed - is deletion of rows, with animation. I spent many hours trying to do this, and this is what I'm doing:

// get current index patch
UITableView* table = [super tableView];
NSIndexPath *indexPath = [table indexPathForSelectedRow];

//delete row in data source
TTListDataSource * source = (TTListDataSource *)self.dataSource;
[source.items removeObjectAtIndex:indexPath.row]; 

// delete row from the table, with animation
[table deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];

After this code runs the error appears: [NSCFArray objectAtIndex:]: index (0) beyond bounds (0)

I'm using the class inherited from the TTTableViewController. And I doesn't implement the DataSourceDelegate or TableViewDelegate because I'm using the Three20 as much as possible. So, this is how I create datasource:

for(NSDictionary *album in (NSArray *)albums){

TTTableRightImageItem *item = [TTTableRightImageItem itemWithText:@"name"  
            imageURL:@"image url" 
           defaultImage:nil 
          imageStyle:TTSTYLE(rounded)
           URL:@"url of selector where I actually catch the tap on a row"];
[tableItems addObject:item];
}
self.dataSource = [TTListDataSource dataSourceWithItems:tableItems];

I read this article (article) but it doesn't help :(

So, I know that this is very simple for gurus from this site. Can you just give me advanced sample of how to do this

Thanks

A: 

The first thing I spot is that you're deleting a row from the table when the table is not in editing mode.

lyonanderson
ok. it's weighty remark. I've added the line "table.editing = YES;", just after the line "NSIndexPath *indexPath = [table indexPathForSelectedRow];". The result is the same :(
Dmitry
The class TTSectionedDataSource would not be sufficient for use in an editable table as it does not implement tableView:commitEditingStyle:forRowAtIndexPath. Subclass TTSectionedDataSource and implement ableView:commitEditingStyle:forRowAtIndexPath. In this method delete the item, then call didDeleteObject. This method will notify your controller and do the animation.
lyonanderson
Actually I need only to remove the row programmatically, with animation. Like here: http://stackoverflow.com/questions/915095/how-to-delete-a-row-in-uitableview-manually , but with Three20.I noticed that there are "- (void)removeItemAtIndexPath:(NSIndexPath*)indexPath" method in TTSectionedDataSource. But it throwing an error!! Maybe it's a bug in Three20??
Dmitry
If I'm not mistaken the member items within the TTSectionedDataSource is an array or arrays - one for each section. In your code you are removing the whole array, which will remove all the items in that section. So you should do something like: NSArray* section = [source.items objectAtIndex:indexPath.section]; [section removeObjectAtIndex:indexPath.row];
lyonanderson
hum, it's true. I've modified the source above. But now I see strange behavior. When I run the code above, I see the row deletion, and just after animation completed - application terminates with error "Program received signal: “EXC_BAD_ACCESS”."
Dmitry
How many rows are in the section? Is it the only row? Looks like you have a memory problem try turning on NSZombies: http://www.cocoadev.com/index.pl?NSZombieEnabled to see if you're over releasing somewhere.
lyonanderson
yep. it's definitely because of only one row in the table. And it looks like something strange happening with the Sections. Because when I change TTSectionedDataSource to TTListDataSource, everything is starting to work fine! I don't really matter about sections, so it's fine for me to use TTListDataSource. however, I really appreciate that you spent your time helping me :)Thank you a lotPSI've modified the code above so you can see the working version
Dmitry
A: 

I also got "EXC_BAD_ACCESS" in model:didDeleteObject:atIndexPath: but I got that problem solved.

To delete a row in a TTTableViewController you need to implement tableView:commitEditingStyle: in your DataSource implementation like this:

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle 
        forRowAtIndexPath:(NSIndexPath *)indexPath {
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        id object = [[self.items objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];

        [self.model didDeleteObject:object atIndexPath:indexPath];
    }
}

You also need to implement tableView:willRemoveObject:atIndexPath: in your DataSource:

- (NSIndexPath*) tableView:(UITableView *)tableView willRemoveObject:(id)object atIndexPath:(NSIndexPath *)indexPath {
    // delete the object
    [object deleteFromDB];

    // removeItemAtIndexPath returns YES if the section is removed
    if ([self removeItemAtIndexPath:indexPath andSectionIfEmpty:YES]) {
        // remove an index path only to that section
        return [NSIndexPath indexPathWithIndex:indexPath.section];
    } else {
        return indexPath;
    }
}

The trick is to change the NSIndexPath you return to only contain the section of it gets empty. Then the code in TTTableViewController removes the section instead of the cell.

HTH

Christian