在项目中为了提升用户体验,需要在2G/3G/4G网络情况下,提供一个无图模式(省流量模式)。我们的APP需求是:在用户开启了无图模式之后,如果当前网络是2G/3G/4G网络,则项目中加载图片的地方需要显示“点击加载图片”,当用户确认点击的情况下,才去加载图片。
无图模式下的判断逻辑如下:
- 如果目标图片之前已经加载过了,则显示已经加载过的图片;
- 如果目标图片之前没有加载过,则只显示一个placeholderImage,并且显示文案“点击加载图片”,当用户确认点击之后,再加载目标图片。
几点说明:
- 为了方便管理图片以及判断图片是否已经加载过,这里使用第三方库SDWebImage来管理。
- 网络情况判断推荐使用Reachability第三方库。
实现思路:
因为项目中之前已经使用了SDWebImage对图片进行管理,为了快速实现这个功能,这里创建了UIButton和UIImageView的扩展,并在扩展中新增了网络加载图片的方法。当开启了无图模式并且目标图片没有加载过时,将一个相同大小的UIButton---coverButton加在当前视图(UIButton或UIImageView)上,coverButton负责显示“点击加载图片”以及点击事件响应。
下面直接上代码(以UIButton为例):
#import "UIButton+YLNoImageModel.h"
#import "UIButton+WebCache.h"
#import "objc/runtime.h"
#import "UIImage+YLResize.h"
static void *kCoverButtonTag = &kCoverButtonTag; ///< 覆盖按钮,点击加载
static void *kLoadImageUrl = &kLoadImageUrl; ///< 图片url
static void *kHolderImage = &kHolderImage; ///< 占位图片
@implementation UIButton (YLNoImageModel)
-(void)yl_setNoImageModelWithUrl:(NSURL *)url placeHolderImage:(UIImage *)holder
{
UIImage *holderImg = [holder resizeToSize:self.bounds.size];
if(kYLNoImageModeIsAvaliable){
//开启了无图模式
//异步判断是否已经加载过了当前图片
[[SDWebImageManager sharedManager]cachedImageExistsForURL:url completion:^(BOOL isInCache) {
if(isInCache){
//如果已经加载过了,直接加载
if(self.coverButton){
[self.coverButton removeFromSuperview];
}
[self sd_setImageWithURL:url forState:UIControlStateNormal
placeholderImage:holderImg];
}else{
//如果没有加载过,则显示点击查看显示图片
[self setImage:holderImg forState:UIControlStateNormal];
self.loadImageUrl = url;
self.holderImage = holderImg;
if(!self.coverButton){
self.coverButton = [UIButton buttonWithType:UIButtonTypeCustom];
self.coverButton.titleLabel.font = [UIFont systemFontOfSize:20];
[self.coverButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[self.coverButton setTitle:@"点击加载图片" forState:UIControlStateNormal];
self.coverButton.contentMode = UIViewContentModeCenter;
}
[self.coverButton addTarget:self action:@selector(coverButtonAction) forControlEvents:UIControlEventTouchUpInside];
self.coverButton.frame = self.bounds;
[self addSubview:self.coverButton];
}
}];
}else{
//未开启无图模式
if(self.coverButton){
[self.coverButton removeFromSuperview];
}
[self sd_setImageWithURL:url forState:UIControlStateNormal placeholderImage:holderImg];
}
}
-(UIButton *)coverButton
{
return (UIButton *)objc_getAssociatedObject(self, kCoverButtonTag);
}
-(void)setCoverButton:(UIButton *)btn
{
objc_setAssociatedObject(self, kCoverButtonTag, btn, OBJC_ASSOCIATION_RETAIN);
}
-(NSURL *)loadImageUrl
{
return (NSURL *)objc_getAssociatedObject(self, kLoadImageUrl);
}
-(void)setLoadImageUrl:(NSURL *)url
{
objc_setAssociatedObject(self, kLoadImageUrl, url, OBJC_ASSOCIATION_COPY);
}
-(UIImage *)holderImage
{
return (UIImage *)objc_getAssociatedObject(self, kHolderImage);
}
-(void)setHolderImage :(UIImage *)img
{
objc_setAssociatedObject(self, kHolderImage, img, OBJC_ASSOCIATION_RETAIN);
}
-(void)coverButtonAction
{
if(self.coverButton){
[self.coverButton removeFromSuperview];
}
[self sd_setImageWithURL:self.loadImageUrl forState:UIControlStateNormal placeholderImage:self.holderImage];
}
@end
至于网络条件判断,请参考Reachability,在项目中监听到网络改变之后保存一个标示kYLNoImageModeIsAvaliable在本地。
使用方法详见:YLNoImageModel
以上是我的实现方法,如果有其他更好的实现方法,请在文章后面留言告诉我一声,谢谢!