iOS开发造轮子 | 封装一个自带loading的imageView

iOS开发造轮子 | 封装一个自带loading的imageView_第1张图片
三笠

为什么要封装这样一个东西?

来自实际项目:
用户点击按钮,弹出hud,hud里有一个imageView,imageView需加载后台设置的网络图片。如下:

iOS开发造轮子 | 封装一个自带loading的imageView_第2张图片

现在的问题是:这张图片比较大,加载需要一点时间,在加载的这段时间内,图片显示的是默认的placeholder image。
如果用户网络不太好,可能这张图需要加载个3秒,这三秒内用户看到的都是placeholder image,这个时候用户可能会想:“这个是啥子哦!”,然后没等图片加载出来就点击hud取消了。
用户之所以会懵逼,是因为他不知道图片还在加载中,切确的说是我们没有友好的告诉他图片还在加载中。

那么怎样告诉用户图片还在加载中呢?

思路:在图片上放一个loading,图片加载完成前显示loading,加载完成后移除loading。

开始封装

用到的三方库:
1.Masonry (方便布局)
2.'ReactiveCocoa','~>2.1.8' (简化KVO的写法)

一.创建一个继承UIImageView的子类,并规定它的构造方法:

#pragma mark - 构造方法
/**
 构造方法

 @param placeholderImage 默认占位图
 @return 带默认占位图的loading imageView
 */
- (instancetype)initWithPlaceholderImage:(UIImage *)placeholderImage;

二.在初始化时就添加loading

#pragma mark - 添加loading
/** 添加loading */
- (void)addLoadingView{
    // 背景
    _loadingView = [[UIView alloc]init];
    [self addSubview:_loadingView];
    _loadingView.backgroundColor = [UIColor colorWithWhite:0.5 alpha:0.5];
    [_loadingView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.edges.mas_equalTo(UIEdgeInsetsMake(0, 0, 0, 0));
    }];
    
    // 动画图片
    UIImageView *animationImageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"haha"]];
    [_loadingView addSubview:animationImageView];
    animationImageView.layer.cornerRadius = 20;
    animationImageView.clipsToBounds = YES;
    [animationImageView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.center.mas_equalTo(_loadingView.superview);
        make.size.mas_equalTo(CGSizeMake(40, 40));
    }];
    
    // 设置动画
    CABasicAnimation *animation =  [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
    animation.autoreverses = NO;
    animation.fromValue    = [NSNumber numberWithFloat:0.f];
    animation.toValue      = [NSNumber numberWithFloat: M_PI *2];
    animation.duration     = 0.1; // 每秒10转,闪瞎你的眼
    animation.repeatCount  = MAXFLOAT; // 一直转
    animation.fillMode     = kCAFillModeForwards;
    
    [animationImageView.layer addAnimation:animation forKey:nil];
}

三.获取图片加载完成的那个点

判断图片是否加载完成我用的一种间接方式:监听imageView的image,如果image变化就说明加载完成:

#pragma mark - 监听image的变化
/** 监听image的变化 */
- (void)observeImageChange{
    [RACObserve(self, image) subscribeNext:^(id x) {
        if (![x isEqual:_placeholderImage]) {
            // 如果图片改变,移除loading图
            [self removeLoadingView];
        }
    }];
}

四.加载完成后移除loading

#pragma mark - 移除loading
/** 移除loading */
- (void)removeLoadingView{
    [_loadingView removeFromSuperview];
    _loadingView = nil;
}

提供一个demo供参考

6翻了的demo

温馨提示

运行demo前请做好心理准备,当心被闪瞎。

你可能感兴趣的:(iOS开发造轮子 | 封装一个自带loading的imageView)