如果没有行,PrefetchRowsAt将无法工作

Guy*_*her 9 prefetch uitableview ios uicollectionview swift

我正在使用新prefetchDataSourceUITableView(也可以应用于UICollectionView.我遇到的问题如下:

  1. 我正在实施func tableView(_ tableView: UITableView, prefetchRowsAt indexPaths: [IndexPath])哪个工作得很好.

  2. 我使用的array是以15个元素开头的.所以numberOfRowsInSection最初将返回array.count15.

  3. 我想要的是prefetchRowsAt函数告诉我当我们从行中运行时,以便从我自己的源获取新数据,将这些数据附加到array然后reloadData(),这将反过来增加numberOfRowsInSection.

  4. 问题是prefetchRowsAt不会超出第15行,因为它受到numberOfRowsInSection我指定的限制.基本上,我卡住了.基本上,当我在第5行时,我希望它告诉我开始预取第16行.

我尝试和工作的一个解决方案是将计数numberOfRowsInSection增加到100,然后在我获取新数据时放置占位符单元格.但滚动条看起来太小,因为它预计有100个项目,所以UX不会那么好.

也许我在第3步中使用的模式是错误的(附加到数组和reloadData)?或者你能想到另一个更清洁的问题解决方案吗?

提前致谢!

0xx*_*xxD 4

我想我已经理解你的意思了:你的类有一个 mutableArray 来存储要显示的 Cell 的数据模型。每次返回的资源请求数为15。

  • 第一次:获取的数据计数为 15,当用户滚动到第 5 个索引路径单元格时,您希望预先向服务器请求下一个资源。获取请求后,您的 mutableArray 的计数为 30

  • 第二次:当用户滚动到第 25 个索引路径单元格时,您希望从服务器预先获取下一个资源。获取请求后,您的 mutableArray 的计数为 45

  • 只要用户滑动屏幕,就永远请求下次资源

OK,并不是必须使用prefetchDataSource(仅iOS 10可用),而是可以使用dataSource。

当然,如果您只在iOS 10中运行您的应用程序,您可以通过实现 prefetch 方法对 Cell 中的元数据(如预缓存图像)进行网络请求。如果没有,您可以使用 cellForRowAtIndexPath(tableView) 或 cellForItemAtIndexPath(collectionView)

  • 对于 UITableView

    表视图:cellForRowAtIndexPath:

  • 对于 UICollectionView

    集合视图:cellForItemAtIndexPath:

此外,我不建议您使用scrollViewDidScroll

因为cell的高度通常会随着数据的变化而变化,如果会比较贵。

您的代码可以像下面的代码一样: (UICollectionView)

@interface YourCollectionView()
@property (nonatomic, strong) SDWebImagePrefetcher *imagePrefetcher;
@end

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
   // Check current indexPath

    NSInteger distance = self.array.count - indexPath.row-1;

    if (distance <= 10) {
        [self loadingMoreData];
    }

    // Preload the ten image into the cache, if you need your app to be compatible with iOS10 below. 
        NSMutableArray <NSURL*> *URLsArray = [[NSMutableArray alloc] init];

   for (NSInteger i = 1; i <= 10; i++) {
        NSInteger y = currentLastIndexRow + i;
        if (y > self.array.count-1) {
            break;
        }
        YourModel *model = self.array[indexPath.item];
        ImageModel *image = model.image;
        [URLsArray addObject:[NSURL URLWithString:image.httpsURL]];
    }
    [self.imagePrefetcher prefetchURLs:URLsArray];


    YourCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:CellIdentifier forIndexPath:indexPath];

    // setting your Cell

    [cell setNeedsLayout];
    return cell;
}
Run Code Online (Sandbox Code Playgroud)

如果您的应用程序不需要兼容iOS10以下,您可以将预加载代码放入prefetch方法中。

BTW:如果您认为我的答案有效,请毫不犹豫地采纳它:)


#Updates:关于如何重新加载:您可以使用 KVO 来监视数组,例如:

[self addObserver:self forKeyPath:@"array" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
Run Code Online (Sandbox Code Playgroud)

并实现这个方法

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{    
    if([keyPath isEqualToString:@"array"])
    {
        if(!change) return;

        id oldC = [change objectForKey:NSKeyValueChangeOldKey];
        id newC = [change objectForKey:NSKeyValueChangeNewKey];
        UICollectionView *cv = selfWeak.collectionView;

        // changes is non-nil, so we just need to update 
        [cv performBatchUpdates:^{
        // delete reload insert..

        } completion:^(BOOL finished) {
            // do somethind , like scrollToItemAtIndexPath
        }];

    }
}
Run Code Online (Sandbox Code Playgroud)