IOS(swift)-scrollView(tableView) ·图片加载逻辑的优化

Table View 中图片加载逻辑的优化
虽然这种优化方式在现在的机能和网络环境下可能看似不那么必要,但在我最初看到这个方法是的 09 年(印象中是 Tweetie 作者在 08 年写的 Blog,可能有误),遥想 iPhone 3G/3GS 的机能,这个方法为多图的 table view 的性能带来很大的提升,也成了我的秘密武器。而现在,在移动网络环境下,你依然值得这么做来为用户节省流量。

先说一下原文的思路:

当用户手动 drag table view 的时候,会加载 cell 中的图片;
在用户快速滑动的减速过程中,不加载过程中 cell 中的图片(但文字信息还是会被加载,只是减少减速过程中的网络开销和图片加载的开销);
在减速结束后,加载所有可见 cell 的图片(如果需要的话);
问题 1:
前面提到,刚开始拖动的时候,dragging 为true,decelerating为false;decelerate过程中,dragging和decelerating都为true;decelerate 未结束时开始下一次拖动,dragging和decelerating依然都为true。所以无法简单通过table view的dragging和decelerating判断是在用户拖动还是减速过程。

解决这个问题很简单,添加一个变量如userDragging,在 willBeginDragging中设为true,didEndDragging中设为false。那么tableView: cellForRowAtIndexPath: 方法中,是否load 图片的逻辑就是:

if (!self.userDragging && tableView.decelerating) {
     cell.pictureView.image = nil;
     println("拖动中和减速中,不显示图片")
} else {
     // code for loading image from network or disk
     println("拖动和减速结束,显示图片")
}

问题 2:
这么做的话,decelerate结束后,屏幕上的 cell 都是不带图片的,解决这个问题也不难,你需要一个形如loadImageForVisibleCells的方法,加载可见cell的图片:

func loadImageForVisibleCells(){
        var cells:NSArray = self.tableView.visibleCells()
        for cell in cells {
            var indexPath:NSIndexPath = self.tableView.indexPathForCell(cell as! UITableViewCell)!
            self.setupCell(cell as! TableViewCell, widthIndexPath: indexPath)
        }
}

问题 3:
这个问题可能不容易被发现,在减速过程中如果用户开始新的拖动,当前屏幕的cell并不会被加载(前文提到的调用顺序问题导致),而且问题 1 的方案并不能解决问题 3,因为这些 cell 已经在屏上,不会再次经过 cellForRowAtIndexPath 方法。虽然不容易发现,但解决很简单,只需要在 scrollViewWillBeginDragging: 方法里也调用一次 loadImageForVisibleCells 即可。

再优化
上述方法在那个年代的确提升了table view的performance,但是你会发现在减速过程最后最慢的那零点几秒时间,其实还是会让人等得有些心急,尤其如果你的 App 只有图片没有文字。在 iOS 5 引入了 scrollViewWillEndDragging: withVelocity: targetContentOffset: 方法后,配合 SDWebImage,我尝试再优化了一下这个方法以提升用户体验:

如果内存中有图片的缓存,减速过程中也会加载该图片
如果图片属于 targetContentOffset 能看到的 cell,正常加载,这样一来,快速滚动的最后一屏出来的的过程中,用户就能看到目标区域的图片逐渐加载
你可以尝试用类似 fade in 或者 flip 的效果缓解生硬的突然出现(尤其是像本例这样只有图片的 App)
核心代码:

func scrollViewWillBeginDragging(scrollView: UIScrollView) {
        self.userDragging = true
        self.targetRect = nil;
        self.loadImageForVisibleCells()
}

func scrollViewWillEndDragging(scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {

        var targetRect:CGRect = CGRectMake(targetContentOffset.memory.x, targetContentOffset.memory.y, scrollView.frame.size.width, scrollView.frame.size.height)
         self.targetRect = NSValue(CGRect: targetRect)
}

func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
        println("结束减速")
        self.targetRect = nil;
        self.loadImageForVisibleCells()
}

是否需要加载图片的逻辑:

var shouldLoadImage:Bool = true
//判断是否重叠
if(self.targetRect != nil  && CGRectIntersectsRect(self.targetRect!.CGRectValue(), cellFrame)){
 //判断是否有缓存,加载缓存
   var manager:SDWebImageManager=SDWebImageManager.sharedManager()
   var cache:SDImageCache = manager.imageCache
   var key:String = manager.cacheKeyForURL(targetURL)
     if((cache.imageFromMemoryCacheForKey(key)) != nil){
                            shouldLoadImage = false
      }
}               
//如果没有缓存,缓存图片
if(shouldLoadImage){
}

更值得高兴的是,通过判断是否 nil,targetRect 同时起到了原来 userDragging 的作用。

Paste_Image.png
Paste_Image.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值