YapDatabase icon indicating copy to clipboard operation
YapDatabase copied to clipboard

Wiki enhancement proposal: Animating updates in TableViews & CollectionViews

Open jongarate opened this issue 8 years ago • 2 comments

While trying to implement the self-updating UITableView paradigm using Views as stated in the wiki, I've stumbled upon several cases of NSInternalInconsistencyException crashes. As evidenced by this and this, despite what Apple Docs say in Ordering of Operations and Index Paths the order in which different change operations are performed matters, and a lot.

In my particular case I ended up performing a reordering of the changes prior to sending them to the UITableView:

    NSMutableArray * fooDeletes = [[NSMutableArray alloc] init];
    NSMutableArray * fooUpdates = [[NSMutableArray alloc] init];
    NSMutableArray * fooInserts = [[NSMutableArray alloc] init];

    for (YapDatabaseViewRowChange *rowChange in rowChanges)
    {
        switch (rowChange.type)
        {
            case YapDatabaseViewChangeDelete :
            {
                [fooDeletes addObject:rowChange.indexPath];
                break;
            }
            case YapDatabaseViewChangeInsert :
            {
                [fooInserts addObject:rowChange.newIndexPath];
                break;
            }
            case YapDatabaseViewChangeMove :
            {
                [fooDeletes addObject:rowChange.indexPath];
                [fooInserts addObject:rowChange.newIndexPath];
                break;
            }
            case YapDatabaseViewChangeUpdate :
            {
                [fooUpdates addObject:rowChange.indexPath];
                break;
            }
        }
    }

    [delegate beginTableViewUpdates];

    // First deletes
    for (NSIndexPath * path in fooDeletes) {
        [delegate listRowChangeDelete:path];
    }

    // Next updates
    for (NSIndexPath * path in fooUpdates) {
        [delegate listRowChangeUpdate:path];
    }

    // Finally inserts
    for (NSIndexPath * path in fooInserts) {
        [delegate listRowChangeInsert:path];
    }

    [delegate endTableViewUpdates];

I thought that some mention to this topic could greatly enhance the Animating updates in TableViews & CollectionViews wiki (particularly the Full animation example bit).

jongarate avatar Jun 09 '16 10:06 jongarate

I'm experiencing similar behavior with a collection view controller and performBatchUpdates. Your solution doesn't seem to fix it.

This has been an ongoing frequent crash for our users, but the good news is it doesn't appear ~~at all~~ in ios10.

Edit: I am actually able to reproduce this in iOS10, but it's much less rare. =/

Are you seeing this crash in iOS 10 @jongarate ?

michaelkirk avatar Sep 24 '16 21:09 michaelkirk

Haven't got such issues neither on development nor production fields. iOS 10 seems totally fine as well.

In my case, I'm not using performBatchUpdates at all, each change action is fired up individually. For completion's sake, this is how the final calls are described in the delegate of the original code excerpt:

- (void)listRowChangeDelete:(NSIndexPath *)index {
    [self.tableView deleteRowsAtIndexPaths:@[ index ]
                              withRowAnimation:UITableViewRowAnimationFade];
}

- (void)listRowChangeInsert:(NSIndexPath *)index {
    [self.tableView insertRowsAtIndexPaths:@[ index ]
                              withRowAnimation:UITableViewRowAnimationFade];
}

- (void)listRowChangeUpdate:(NSIndexPath *)index {
    [self.tableView reloadRowsAtIndexPaths:@[ index ]
                              withRowAnimation:UITableViewRowAnimationNone];
}

- (void)reloadTable {
    [self.tableView reloadData];
}

- (void)beginTableViewUpdates {
    [self.tableView beginUpdates];
}

- (void)endTableViewUpdates {
    [self.tableView endUpdates];
}

Perhaps try individual updates each time instead of grouping them?

jongarate avatar Sep 26 '16 08:09 jongarate