ios – 在重用UITableViewCell时使用SDWebImage处理图像下载

ios – 在重用UITableViewCell时使用SDWebImage处理图像下载,第1张

概述我使用第三方库SDWeb Image为我的UITableView单元下载图像,在单元格中创建UIImageView并在配置像这样的单元格时触发请求. [imageView setImageWithURL:[NSURL URLWithString:imageUrl] placeholderImage:[UIImage imageNamed:@"default.jpg"] completed:^(UI 我使用第三方库SDWeb Image为我的UItableVIEw单元下载图像,在单元格中创建UIImageVIEw并在配置像这样的单元格时触发请求.

[imageVIEw setimageWithURL:[NSURL URLWithString:imageUrl] placeholderImage:[UIImage imagenamed:@"default.jpg"] completed:^(UIImage *image,NSError *error,SDImageCacheType cacheType) {    }];

它的工作正常,但是当我快速滚动时,大多数图像都没有完全下载(我可以在查尔斯看到),因为图像没有被缓存.即使我的单元格被重用,如何缓存已发送的请求,以便相同的请求不会多次进行.

请忽略任何拼写错误:)

解决方法 有效的iOS 10,不再需要我原来答案的手动预取代码.只需设置一个prefetchDataSource.例如,在Swift 3中:

overrIDe func vIEwDIDLoad() {    super.vIEwDIDLoad()    tableVIEw.prefetchDataSource = self}

然后有一个prefetchRowsAtIndexPaths,它使用SDWebImagePrefetcher来获取行

extension VIEwController: UItableVIEwDataSourcePrefetching {    public func tableVIEw(_ tableVIEw: UItableVIEw,prefetchRowsAt indexPaths: [IndexPath]) {        let urls = indexPaths.map { baseURL.appendingPathComponent(images[
overrIDe func tableVIEw(_ tableVIEw: UItableVIEw,cellForRowAt indexPath: IndexPath) -> UItableVIEwCell {    let cell = tableVIEw.dequeueReusableCell(withIDentifIEr: "Cell",for: indexPath)    let url = baseURL.appendingPathComponent(images[indexPath.row])    cell.imageVIEw?.sd_setimage(with: url,placeholderImage: placeholder)    return cell}
.row]) } SDWebImagePrefetcher.shared().prefetchURLs(urls) }}

你可以拥有标准的cellForRowAt:

extension VIEwController: UItableVIEwDataSourcePrefetching {    public func tableVIEw(_ tableVIEw: UItableVIEw,prefetchRowsAt indexPaths: [IndexPath]) {        let requests = indexPaths.map { URLRequest(url: baseURL.appendingPathComponent(images[
overrIDe func tableVIEw(_ tableVIEw: UItableVIEw,for: indexPath)    let url = baseURL.appendingPathComponent(images[indexPath.row])    cell.imageVIEw?.af_setimage(withURL: url,placeholderImage: placeholder)    return cell}
.row])) } AlamofireImage.ImageDownloader.default.download(requests) }}

就个人而言,我更喜欢AlamofireImage.所以UItableVIEwDataSourcePrefetching略有不同

[self.tableVIEw reloadData];dispatch_async(dispatch_get_main_queue(),^{    [self prefetchImagesFortableVIEw:self.tableVIEw];});

显然,cellForRowAt会使用af_setimage:

- (voID)scrollVIEwDIDEndDecelerating:(UIScrollVIEw *)scrollVIEw {    [self prefetchImagesFortableVIEw:self.tableVIEw];}- (voID)scrollVIEwDIDEndDragging:(UIScrollVIEw *)scrollVIEw willDecelerate:(BOol)decelerate {    if (!decelerate)        [self prefetchImagesFortableVIEw:self.tableVIEw];}

我在下面的原始答案显示,对于Objective-C,你如何在10之前的iOS版本中做到这一点(我们必须进行自己的预取计算).

这种取消不再可见的单元格下载的行为恰恰是在快速滚动时保持异步图像检索响应的原因,即使连接速度较慢也是如此.例如,如果您快速向下滚动到tablevIEw的第100个单元格,您实际上不希望该图像检索在前面99行(不再可见)的图像检索后面积压.我建议单独保留UIImageVIEw类别,但如果要为可能滚动到的单元格预取图像,请使用SDWebImagePrefetcher.

例如,在我调用reloadData的地方,我还预先获取当前可见单元格之前和之后的十个单元格的图像:

#pragma mark - Prefetch cellsstatic NSInteger const kPrefetchRowCount = 10;/** Prefetch a certain number of images for rows prior to and subsequent to the currently visible cells * * @param  tableVIEw   The tablevIEw for which we're going to prefetch images. */- (voID)prefetchImagesFortableVIEw:(UItableVIEw *)tableVIEw {    NSArray *indexPaths = [self.tableVIEw indexPathsForVisibleRows];    if ([indexPaths count] == 0) return;    NSIndexPath *minimumIndexPath = indexPaths[0];    NSIndexPath *maximumIndexPath = [indexPaths lastObject];    // they should be sorted already,but if not,update min and max accordingly    for (NSIndexPath *indexPath in indexPaths) {        if ([minimumIndexPath compare:indexPath] == NSOrderedDescending)            minimumIndexPath = indexPath;        if ([maximumIndexPath compare:indexPath] == NSOrderedAscending)            maximumIndexPath = indexPath;    }    // build array of imageURLs for cells to prefetch    NSMutableArray<NSIndexPath *> *prefetchIndexPaths = [NSMutableArray array];    NSArray<NSIndexPath *> *precedingRows = [self tableVIEw:tableVIEw indexPathsForPrecedingRows:kPrefetchRowCount fromIndexPath:minimumIndexPath];    [prefetchIndexPaths addobjectsFromArray:precedingRows];    NSArray<NSIndexPath *> *followingRows = [self tableVIEw:tableVIEw indexPathsForFollowingRows:kPrefetchRowCount fromIndexPath:maximumIndexPath];    [prefetchIndexPaths addobjectsFromArray:followingRows];    // build array of imageURLs for cells to prefetch (how you get the image URLs will vary based upon your implementation)    NSMutableArray<NSURL *> *urls = [NSMutableArray array];    for (NSIndexPath *indexPath in prefetchIndexPaths) {        NSURL *url = self.objects[indexPath.row].imageURL;        if (url) {            [urls addobject:url];        }    }    // Now prefetch    if ([urls count] > 0) {        [[SDWebImagePrefetcher sharedImagePrefetcher] prefetchURLs:urls];    }}/** RetrIEve NSIndexPath for a certain number of rows preceding particular NSIndexPath in the table vIEw. * * @param  tableVIEw  The tablevIEw for which we're going to retrIEve indexPaths. * @param  count      The number of rows to retrIEve * @param  indexPath  The indexPath where we're going to start (presumably the first visible indexPath) * * @return            An array of indexPaths. */- (NSArray<NSIndexPath *> *)tableVIEw:(UItableVIEw *)tableVIEw indexPathsForPrecedingRows:(NSInteger)count fromIndexPath:(NSIndexPath *)indexPath {    NSMutableArray *indexPaths = [NSMutableArray array];    NSInteger row = indexPath.row;    NSInteger section = indexPath.section;    for (NSInteger i = 0; i < count; i++) {        if (row == 0) {            if (section == 0) {                return indexPaths;            } else {                section--;                row = [tableVIEw numberOfRowsInSection:section] - 1;            }        } else {            row--;        }        [indexPaths addobject:[NSIndexPath indexPathForRow:row inSection:section]];    }    return indexPaths;}/** RetrIEve NSIndexPath for a certain number of following particular NSIndexPath in the table vIEw. * * @param  tableVIEw  The tablevIEw for which we're going to retrIEve indexPaths. * @param  count      The number of rows to retrIEve * @param  indexPath  The indexPath where we're going to start (presumably the last visible indexPath) * * @return            An array of indexPaths. */- (NSArray<NSIndexPath *> *)tableVIEw:(UItableVIEw *)tableVIEw indexPathsForFollowingRows:(NSInteger)count fromIndexPath:(NSIndexPath *)indexPath {    NSMutableArray *indexPaths = [NSMutableArray array];    NSInteger row = indexPath.row;    NSInteger section = indexPath.section;    NSInteger rowCountForSection = [tableVIEw numberOfRowsInSection:section];    for (NSInteger i = 0; i < count; i++) {        row++;        if (row == rowCountForSection) {            row = 0;            section++;            if (section == [tableVIEw numberOfSections]) {                return indexPaths;            }            rowCountForSection = [tableVIEw numberOfRowsInSection:section];        }        [indexPaths addobject:[NSIndexPath indexPathForRow:row inSection:section]];    }    return indexPaths;}

同样,只要我停止滚动,我也会这样做:

就我如何预取十个前后单元格而言,我这样做:

总结

以上是内存溢出为你收集整理的ios – 在重用UITableViewCell时使用SDWebImage处理图像下载全部内容,希望文章能够帮你解决ios – 在重用UITableViewCell时使用SDWebImage处理图像下载所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1081957.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-27
下一篇 2022-05-27

发表评论

登录后才能评论

评论列表(0条)

保存