iOS table view diffable data source and prefetch
Asked Answered
Z

0

6

What is the correct way of using NSDiffableDataSourceSnapshot and - (void)tableView:(nonnull UITableView *)tableView prefetchRowsAtIndexPaths:(nonnull NSArray<NSIndexPath *> *)indexPaths.

It seems that every time prefetch reloads table view, table view asks for more prefetching, after calling apply snapshot, creating infinite loop.

- (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];
}

And here is prefetch method:

- (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];
    }
}

Model queue is just operation queue:

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

Is there a way to use prefetching with diffable data sources without apply asking for more indexes?

EDIT:

So calling reloadData in prefetch methods makes infinite loop.. According to https://andreygordeev.com/2017/02/20/uitableview-prefetching/

WARNING: do not call tableView.reloadData() or tableView.reloadRows(...) from tableView(_ tableView: UITableView, prefetchRowsAt indexPaths: [IndexPath]) method! These methods provoke UITableView to call prefetchRowsAt... and thus lead to infinity loop.

Soo.. how has Apple intended for prefetching to be used with Diffable Data Sources? ... -.-

Zapateado answered 15/3, 2021 at 11:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.