UITableView 中动画插入/删除的 2 个 NSArray 的差异

发布于 2024-08-25 05:11:20 字数 236 浏览 5 评论 0原文

在我的应用程序中的某个时刻,我有一个 NSArray,其内容发生了变化。这些内容显示在 UITableView 中。我正在尝试找到一种方法来查找 NSArray 之前和之后的内容之间的差异,以便我可以将正确的索引路径传递给 insertRowsAtIndexPaths:withRowAnimation: 和 deleteRowsAtIndexPaths:withRowAnimation: 以便使更改具有良好的动画效果。有什么想法吗?

谢谢

At some point in my Application, I have an NSArray whose contents change. Those contents are shown in a UITableView. I'm trying to find a way to find the diff between the contents of before and after of the NSArray so i can pass the correct indexPaths to insertRowsAtIndexPaths:withRowAnimation: and deleteRowsAtIndexPaths:withRowAnimation: in order to have the changes nicely animated. Any ideas?

thx

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

哭了丶谁疼 2024-09-01 05:11:20

这是我尝试过的,它似乎有效,如果有人有更好的东西,我很乐意看到它。

[self.tableView beginUpdates];

NSMutableArray* rowsToDelete = [NSMutableArray array];
NSMutableArray* rowsToInsert = [NSMutableArray array];

for ( NSInteger i = 0; i < oldEntries.count; i++ )
{
    FDEntry* entry = [oldEntries objectAtIndex:i];
    if ( ! [displayEntries containsObject:entry] )
        [rowsToDelete addObject: [NSIndexPath indexPathForRow:i inSection:0]];
}

for ( NSInteger i = 0; i < displayEntries.count; i++ )
{
    FDEntry* entry = [displayEntries objectAtIndex:i];
    if ( ! [oldEntries containsObject:entry] )
    [rowsToInsert addObject: [NSIndexPath indexPathForRow:i inSection:0]];
}

[self.tableView deleteRowsAtIndexPaths:rowsToDelete withRowAnimation:UITableViewRowAnimationFade];
[self.tableView insertRowsAtIndexPaths:rowsToInsert withRowAnimation:UITableViewRowAnimationRight];

[self.tableView endUpdates];

Here's is wat i tried and it seems to work, if anyone has anything better, i'd love to see it.

[self.tableView beginUpdates];

NSMutableArray* rowsToDelete = [NSMutableArray array];
NSMutableArray* rowsToInsert = [NSMutableArray array];

for ( NSInteger i = 0; i < oldEntries.count; i++ )
{
    FDEntry* entry = [oldEntries objectAtIndex:i];
    if ( ! [displayEntries containsObject:entry] )
        [rowsToDelete addObject: [NSIndexPath indexPathForRow:i inSection:0]];
}

for ( NSInteger i = 0; i < displayEntries.count; i++ )
{
    FDEntry* entry = [displayEntries objectAtIndex:i];
    if ( ! [oldEntries containsObject:entry] )
    [rowsToInsert addObject: [NSIndexPath indexPathForRow:i inSection:0]];
}

[self.tableView deleteRowsAtIndexPaths:rowsToDelete withRowAnimation:UITableViewRowAnimationFade];
[self.tableView insertRowsAtIndexPaths:rowsToInsert withRowAnimation:UITableViewRowAnimationRight];

[self.tableView endUpdates];
浪菊怪哟 2024-09-01 05:11:20

这个2010年的问题是我在谷歌搜索时发现的。从 iOS 5.0 开始,我们现在还有您真正想要处理的 -[UITableView moveRowAtIndexPath:toIndexPath] 。这是一个比较两个数组并为删除、插入和移动操作生成合适的索引路径的函数。

- (void) calculateTableViewChangesBetweenOldArray:(NSArray *)oldObjects
                                         newArray:(NSArray *)newObjects
                                     sectionIndex:(NSInteger)section
                               indexPathsToDelete:(NSArray **)indexPathsToDelete
                               indexPathsToInsert:(NSArray **)indexPathsToInsert
                                 indexPathsToMove:(NSArray **)indexPathsToMove
                            destinationIndexPaths:(NSArray **)destinationIndexPaths
{

    NSMutableArray *pathsToDelete = [NSMutableArray new];
    NSMutableArray *pathsToInsert = [NSMutableArray new];
    NSMutableArray *pathsToMove = [NSMutableArray new];
    NSMutableArray *destinationPaths = [NSMutableArray new];

    // Deletes and moves
    for (NSInteger oldIndex = 0; oldIndex < oldObjects.count; oldIndex++) {
        NSObject *object = oldObjects[oldIndex];
        NSInteger newIndex = [newObjects indexOfObject:object];

        if (newIndex == NSNotFound) {
            [pathsToDelete addObject:[NSIndexPath indexPathForRow:oldIndex inSection:section]];
        } else if (newIndex != oldIndex) {
            [pathsToMove addObject:[NSIndexPath indexPathForRow:oldIndex inSection:section]];
            [destinationPaths addObject:[NSIndexPath indexPathForRow:newIndex inSection:section]];
        }
    }

    // Inserts
    for (NSInteger newIndex = 0; newIndex < newObjects.count; newIndex++) {
        NSObject *object = newObjects[newIndex];
        if (![oldObjects containsObject:object]) {
            [pathsToInsert addObject:[NSIndexPath indexPathForRow:newIndex inSection:section]];
        }
    }

    if (indexPathsToDelete)     *indexPathsToDelete =    [pathsToDelete copy];
    if (indexPathsToInsert)     *indexPathsToInsert =    [pathsToInsert copy];
    if (indexPathsToMove)       *indexPathsToMove =      [pathsToMove copy];
    if (destinationIndexPaths)  *destinationIndexPaths = [destinationPaths copy];
}

有关如何使用它的示例。假设您正在显示一个人员表格,并将其保存在数组 self.people 中。显示人员的部分索引为 0。

- (void) setPeople:(NSArray <Person *> *)newPeople {
    dispatch_async(dispatch_get_main_queue(), ^{
        [self.tableView beginUpdates];

        NSArray *rowsToDelete, *rowsToInsert, *rowsToMove, *destinationRows;

        [self calculateTableViewChangesBetweenOldArray:self.people
                                              newArray:newPeople
                                          sectionIndex:0
                                    indexPathsToDelete:&rowsToDelete
                                    indexPathsToInsert:&rowsToInsert
                                      indexPathsToMove:&rowsToMove
                                 destinationIndexPaths:&destinationRows
         ];

        self.people = newPeople;

        [self.tableView deleteRowsAtIndexPaths:rowsToDelete withRowAnimation:UITableViewRowAnimationFade];
        [self.tableView insertRowsAtIndexPaths:rowsToInsert withRowAnimation:UITableViewRowAnimationFade];
        [rowsToMove enumerateObjectsUsingBlock:^(NSIndexPath *  _Nonnull oldIndexPath, NSUInteger idx, BOOL * _Nonnull stop) {
            NSIndexPath *newIndexPath = destinationRows[idx];
            [self.tableView moveRowAtIndexPath:oldIndexPath toIndexPath:newIndexPath];
        }];

        [self.tableView endUpdates];
    });
}

This question from 2010 is what I found when I was googling. Since iOS 5.0, we now also have -[UITableView moveRowAtIndexPath:toIndexPath] which you really want to handle as well. Here is a function that compares two arrays and generates suitable indexpaths for the delete, insert and move operations.

- (void) calculateTableViewChangesBetweenOldArray:(NSArray *)oldObjects
                                         newArray:(NSArray *)newObjects
                                     sectionIndex:(NSInteger)section
                               indexPathsToDelete:(NSArray **)indexPathsToDelete
                               indexPathsToInsert:(NSArray **)indexPathsToInsert
                                 indexPathsToMove:(NSArray **)indexPathsToMove
                            destinationIndexPaths:(NSArray **)destinationIndexPaths
{

    NSMutableArray *pathsToDelete = [NSMutableArray new];
    NSMutableArray *pathsToInsert = [NSMutableArray new];
    NSMutableArray *pathsToMove = [NSMutableArray new];
    NSMutableArray *destinationPaths = [NSMutableArray new];

    // Deletes and moves
    for (NSInteger oldIndex = 0; oldIndex < oldObjects.count; oldIndex++) {
        NSObject *object = oldObjects[oldIndex];
        NSInteger newIndex = [newObjects indexOfObject:object];

        if (newIndex == NSNotFound) {
            [pathsToDelete addObject:[NSIndexPath indexPathForRow:oldIndex inSection:section]];
        } else if (newIndex != oldIndex) {
            [pathsToMove addObject:[NSIndexPath indexPathForRow:oldIndex inSection:section]];
            [destinationPaths addObject:[NSIndexPath indexPathForRow:newIndex inSection:section]];
        }
    }

    // Inserts
    for (NSInteger newIndex = 0; newIndex < newObjects.count; newIndex++) {
        NSObject *object = newObjects[newIndex];
        if (![oldObjects containsObject:object]) {
            [pathsToInsert addObject:[NSIndexPath indexPathForRow:newIndex inSection:section]];
        }
    }

    if (indexPathsToDelete)     *indexPathsToDelete =    [pathsToDelete copy];
    if (indexPathsToInsert)     *indexPathsToInsert =    [pathsToInsert copy];
    if (indexPathsToMove)       *indexPathsToMove =      [pathsToMove copy];
    if (destinationIndexPaths)  *destinationIndexPaths = [destinationPaths copy];
}

An example on how to use it. Assume you're displaying a table of people, which you keep in the array self.people. The section index where the people are displayed is 0.

- (void) setPeople:(NSArray <Person *> *)newPeople {
    dispatch_async(dispatch_get_main_queue(), ^{
        [self.tableView beginUpdates];

        NSArray *rowsToDelete, *rowsToInsert, *rowsToMove, *destinationRows;

        [self calculateTableViewChangesBetweenOldArray:self.people
                                              newArray:newPeople
                                          sectionIndex:0
                                    indexPathsToDelete:&rowsToDelete
                                    indexPathsToInsert:&rowsToInsert
                                      indexPathsToMove:&rowsToMove
                                 destinationIndexPaths:&destinationRows
         ];

        self.people = newPeople;

        [self.tableView deleteRowsAtIndexPaths:rowsToDelete withRowAnimation:UITableViewRowAnimationFade];
        [self.tableView insertRowsAtIndexPaths:rowsToInsert withRowAnimation:UITableViewRowAnimationFade];
        [rowsToMove enumerateObjectsUsingBlock:^(NSIndexPath *  _Nonnull oldIndexPath, NSUInteger idx, BOOL * _Nonnull stop) {
            NSIndexPath *newIndexPath = destinationRows[idx];
            [self.tableView moveRowAtIndexPath:oldIndexPath toIndexPath:newIndexPath];
        }];

        [self.tableView endUpdates];
    });
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文