最近有一个需求,在前后台切换的时候,会刷新tableView。由于SDWebImage在切换前后台的时候会清除memory的缓存,重新刷的时候会有图片闪动的问题。
整个解决历程是这样的:
contentSize和contentOffset的禁用
在iOS 11Self-Sizing自动打开后,contentSize和contentOffset都可能发生改变。
可以通过以下方式禁用
self.estimatedRowHeight = 0;
self.estimatedSectionHeaderHeight = 0;
self.estimatedSectionFooterHeight = 0;
然而这个方法并没有用,这个方法只会解决tableView整体的抖动,并不会解决图片的抖动问题。
UIView的隐式动画
接着又尝试了其他方法,由于UIView的隐式动画,也会造成图片的闪动问题。下面代码可以关闭隐式动画。
if (@available(iOS 11.0, *)) {
[UIView setAnimationsEnabled:NO];
[_tableView performBatchUpdates:^{
[_tableView reloadData];
} completion:^(BOOL finished) {
[UIView setAnimationsEnabled:YES];
}];
} else {
[_tableView reloadData];
}
这个方法能解决闪动的问题,但是不能彻底解决闪动的问题,也会偶先闪动。
利用缓存解决
UIImage *cacheImage = [[SDImageCache sharedImageCache] imageFromDiskCacheForKey:url.absoluteString];
[_imageView sd_setImageWithURL:url placeholderImage:cacheImage?cacheImage:placeholderImage];
可以先从缓存中拿到图片,给sd的placeholderImage。这样,原本后台切前台的memory缓存被清理掉,在展示图片的时候先从disk读取(disk中的缓存不会被清理掉),再展示在imageView上。这样,就可以解决闪动的问题,达到预期的效果。
但是,这样做是有瑕疵的。由于[[SDImageCache sharedImageCache] imageFromDiskCacheForKey:url.absoluteString]该方法是同步方法,没有在异步读取,所以会略微卡顿主线程,虽然这种卡顿不明显。
自定义imageView
终极解决方案:
我们会自定义imageView,在imageView中我们会实现cache,这种cache即使后台切前台也不会清除,并且这种cache是异步的,不会卡顿主线程。最终,这个方案完美的解决了这个问题。由于,代码实现稍微有点复杂,这里就不贴代码了。
解决一个问题都有一个过程,我们应该追求的是,不该在很浅的层面上解决问题而暴露其他问题,而是从根源入手,在实现机制上解决问题。