iOS 表视图 diffable 数据源和预取

Mar*_*ger 6 objective-c uitableview uikit ios diffabledatasource

NSDiffableDataSourceSnapshot和的正确使用方法是什么- (void)tableView:(nonnull UITableView *)tableView prefetchRowsAtIndexPaths:(nonnull NSArray<NSIndexPath *> *)indexPaths

似乎每次预取重新加载表视图时,表视图都会在调用apply快照后要求更多预取,从而创建无限循环。

- (void)reloadViews {
    //[self.tableView reloadData];
    
    NSMutableArray *items = [NSMutableArray new];
    for (TCHChannel* channel in self.channels) {
        [items addObject:channel.sid];
    }
    if ([items count] == 0) {
        return;
    }
    
    NSDiffableDataSourceSnapshot<ConversationSectionType*, NSString*> *snapshot =
    [[NSDiffableDataSourceSnapshot<ConversationSectionType*, NSString*> alloc] init];
    ConversationSectionType *main = [ConversationSectionType new];
    main.section = kMain;
    [snapshot appendSectionsWithIdentifiers:@[main]];
    [snapshot appendItemsWithIdentifiers:items intoSectionWithIdentifier:main];
    [self.diffDataSource applySnapshot:snapshot animatingDifferences:NO];
}
Run Code Online (Sandbox Code Playgroud)

这是预取方法:

- (void)tableView:(nonnull UITableView *)tableView prefetchRowsAtIndexPaths:(nonnull NSArray<NSIndexPath *> *)indexPaths {
    for (NSIndexPath *indexPath in indexPaths) {
        TCHChannel *channel = [self channelForIndexPath:indexPath];
        
        NSMutableSet *currentChannelIds = [NSMutableSet new];
        for (ConversationListViewModelUpdateOperation *op in self.modelQueue.operations) {
            [currentChannelIds addObject:[op channelId]];
        }
        if ([currentChannelIds containsObject:channel.sid]) {
            continue;
        }
        
        NSParameterAssert(channel != nil);
        ConversationListViewModelUpdateOperation *op = [[ConversationListViewModelUpdateOperation alloc] initWithChannel:channel cache:self.channelViewModelsCache];
        op.completionBlock = ^{
            dispatch_async(dispatch_get_main_queue(), ^(void){
                [self reloadViews];
            });
        };
        [self.modelQueue addOperation:op];
    }
}
Run Code Online (Sandbox Code Playgroud)

模型队列只是操作队列:

- (NSOperationQueue*)modelQueue {
    if (_modelQueue == nil) {
        _modelQueue = [[NSOperationQueue alloc] init];
        _modelQueue.maxConcurrentOperationCount = 4;
    }
    return _modelQueue;
}
Run Code Online (Sandbox Code Playgroud)

有没有一种方法可以在不apply要求更多索引的情况下对可比较的数据源使用预取?

编辑:

因此,调用reloadData预取方法会造成无限循环。根据https://andreygordeev.com/2017/02/20/uitableview-prefetching/

警告:不要从 tableView(_ tableView: UITableView, prefetchRowsAt indexPaths: [IndexPath]) 方法调用 tableView.reloadData() 或 tableView.reloadRows(...) !这些方法会引发 UITableView 调用 prefetchRowsAt... 从而导致无限循环。

Soo..Apple 打算如何将预取与 Diffable 数据源一起使用?...-.-