iOS开发UITablevView的懒加载

释放双眼,带上耳机,听听看~!

UITablevView的懒加载时列表优化的最重要的方法之一,比如说今日头条就用了懒加载:快速滑动时,不加载图片,滑动将停止时才加载图片。

 

一、UITablevView的懒加载的原理:

1、当用户拖动tableview时,会加载cell中的图片。

2、当用户快速滑过tableview时不加载图片。

3、在tableview滑动即将结束时加载cell中的图片,这样就节省了下载图片和加载图片时的开销(多线程的开辟,内存的消耗 )。

上面的原理要求我们熟悉tableView的各种状态(拖动、滑动、减速、停止)等。我们知道UITableView继承自UIScrollView,而UIScrollView的各中状态我们时可以从它的代理方法中获得,从而也就获得了tableVew的各种状态,见:拖拽UIScrollView时的delegate调用调用顺序。

简单懒加载的核心代码:

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {

    self.targetRect =nil;

   [selfloadVisibleCells];

}




- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inoutCGPoint
*)targetContentOffset {

    CGRect targetRect =
CGRectMake(targetContentOffset->x, targetContentOffset->y, scrollView.frame.size.width,
scrollView.frame.size.height);

    self.targetRect = [NSValuevalueWithCGRect:targetRect];

}




- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {

    self.targetRect =nil;
 

   [self
loadVisibleCells];

}




- (UITableViewCell *)tableView:(UITableView
*)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *cellIdentifier =@"ImageCell";

    ImageCell *cell = [tableView
dequeueReusableCellWithIdentifier:cellIdentifier];

    if (!cell) {

        cell = [[[NSBundlemainBundle]loadNibNamed:@"ImageCell"owner:selfoptions:nil]firstObject];

    }


    [selfloadCell:cellwithIndexPath:indexPath];

}




- (void)loadCell:(ImageCell *)cell withIndexPath:(NSIndexPath *)indexPath {

     NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];       

     CGRect cellFrame = [self.tableView rectForRowAtIndexPath:indexPath];

     if (self.targetRect &&
!CGRectIntersectsRect([self.targetRect CGRectValue],
cellFrame)) {

        //[cell.bigImageView sd_setImageWithUR。。。加载图片

     }

}




- (void) loadVisibleCells {

    NSArray *cells = [self.tableViewvisibleCells];

    for (ImageCell *cellin cells) {




    }

}

 

二、懒加载存在的问题:

1 、我们虽然在减速过程中没有加载图片,但是显示的cell上依然有图片,这是怎么回事?我们知道tableView的cell是重用的,因为我们在滑动停止时才重新加载图片,所以减速过程中还是上次加载的图片。也就是经常说的图片的窜位问题(重用bug)。

2、上面的方案是拖动或滑动即将停止时再加载图片,在减速过程中即使图片缓存过了也不加载,这显然不合理。

 

三、进一步优化:

上面的两个问题归根到底是由于在滑动减速过程中没有对cell的图片做处理,也就是说我们可以在减速过程中,我们对已缓存过的图片也加载。

这就涉及到通过url判断图片是否已缓存,这个如果是手动缓存的话比较麻烦,但别忘了SDWebImage这个神器,它在图片的一步下载和缓存方面做的是非常出色的,对下载过的图片都会根据url自动缓存!所以通过下面的代码就可以得知图片是否有已缓存

SDWebImageManager *manager = [SDWebImageManagersharedManager];

SDImageCache *cache = [manager
imageCache];

NSString *key = [managercacheKeyForURL:targetURL]; //targetURL就是需要加载的图片的URL的NSURL类型

if ([cache imageFromMemoryCacheForKey:key]) {

    //加载图片

}

 

也就是我们在减速的时候每次加载cell时,判断当前的cell中image图片的url和数据模型中的是否一样,不一样的话,就先隐藏cell的图片,然后根据url区加载缓存中的图片,如果加载到了,则显示图片,否则不做处理,这样就解决了窜位的问题。同时也解决了减速不加载已缓存的图片问题!核心代码:

 

if (![[cell.photoViewsd_imageURL]isEqual:targetURL]) {

        cell.photoView.alpha =0.0;

        SDWebImageManager *manager = [SDWebImageManagersharedManager];

        CGRect cellFrame = [self.tableViewrectForRowAtIndexPath:indexPath];

        BOOL shouldLoadImage =
YES;

        if (self.targetRect && !CGRectIntersectsRect([self.targetRectCGRectValue],
cellFrame)) {  //判断是否在减速

            SDImageCache *cache = [manager
imageCache];

            NSString *key = [manager
cacheKeyForURL:targetURL];

            if (![cache
imageFromMemoryCacheForKey:key]) {

                shouldLoadImage = NO;

            }

        }

        if (shouldLoadImage) {

            [cell.bigImageView sd_setImageWithURL:targetURLplaceholderImage:niloptions:SDWebImageHandleCookiescompleted:^(UIImage
*image,NSError *error,
SDImageCacheType cacheType,NSURL *imageURL) {

                if (!error && [imageURL
isEqual:targetURL]) {

                    [UIViewanimateWithDuration:0.25animations:^{

                        cell.bigImageView.alpha =1.0;

                    }];

                }

            }];

       }

    }

 

人已赞赏
0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
有新消息 消息中心
搜索