前言
iOS开发中会遇到很多需要使用进度条表示下载进度的地方。
如图
代码
- 首先是环形动画的封装
- ShowProgress.h
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface ShowProgress : UIView
@property(nonatomic, assign) CGFloat progress;
@property(nonatomic, strong) UIColor *progressBarColor;
@end
NS_ASSUME_NONNULL_END
- ShowProgress.m
#import "ShowProgress.h"
@implementation ShowProgress
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
self.backgroundColor = [UIColor clearColor];
self.progressBarColor = [UIColor blackColor];
}
return self;
}
- (void)drawRect:(CGRect)rect {
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGFloat xCenter = rect.size.width * 0.5;
CGFloat yCenter = rect.size.height * 0.5;
[_progressBarColor set];
//设置圆环的宽度
CGContextSetLineWidth(ctx, 2); //1.5 圆环的宽度
CGContextSetLineCap(ctx, kCGLineCapRound);
CGFloat to = - M_PI * 0.5 + self.progress * M_PI * 2; // 初始值0.05
//半径
CGFloat radius = rect.size.width * 0.5 - 1;
CGContextAddArc(ctx, xCenter, yCenter, radius, - M_PI * 0.5, to, 0);
CGContextStrokePath(ctx);
}
- (void)setProgress:(CGFloat)progress {
_progress = progress;
if (_progress >= 1) {
[self removeFromSuperview];
} else {
[self setNeedsDisplay];
}
}
@end
使用
- 一般是用AFN进行下载
#pragma mark - AFN 下载
- (void)downLoadUrl:(NSString *)urlString
progressBlock:(DownProgressBlock _Nullable)progressBlock
downSuccessBlock:(DownSuccessBlock _Nullable)downSuccessBlock
downFailedBlock:(DownFailedBlock _Nullable)downFailedBlock {
AFHTTPSessionManager *manager = [self manager];
//2.1 创建请求对象
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:urlString]];
__weak typeof(self) weakSelf = self;
NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:^(NSProgress *downloadProgress) {
//进度
CGFloat rate = (100.0 * downloadProgress.completedUnitCount / downloadProgress.totalUnitCount);
[weakSelf _getMainThread:^{
if (progressBlock) {
progressBlock(rate);
}
}];
} destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) {
NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
//response.suggestedFilename后缀名 xxx.mp4
//https://dl.anycdn.cc/data/static/ay/bao.zip
NSString *fullpath = [caches stringByAppendingPathComponent:response.suggestedFilename];
NSURL *filePathUrl = [NSURL fileURLWithPath:fullpath];
return filePathUrl;
} completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) {
//都在主线程
if (error) {
//加载失败
downFailedBlock(error);
}
NSString *file = [[filePath absoluteString] stringByReplacingOccurrencesOfString:@"file://" withString:@""];
NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
if(filePath) {
//加载成功返回路径
downSuccessBlock(file, caches);
}
}];
//3.启动任务
[downloadTask resume];
}
- (AFHTTPSessionManager *)manager {
static AFHTTPSessionManager *manager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if (manager == nil) {
manager = [AFHTTPSessionManager manager];
manager.requestSerializer.timeoutInterval = kTimeoutInterval;
}
});
return manager;
}
#pragma mark - AFN 下载 end
- 通过一个计时器对环形动画的进度填充 ViewController.m
#import "ViewController.h"
#import "ShowProgress.h"
static NSInteger const kMaxTime = 10;
@interface ViewController ()
@property(nonatomic, strong) UIView *backView;
@property(nonatomic, strong) ShowProgress *_Nullable progressView; //下载进度页面
@property(nonatomic, strong) NSTimer *timer;
@property(nonatomic, assign) NSInteger count;
@end
@implementation ViewController
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[self startTask];
}
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor lightGrayColor];
[self.view addSubview:self.backView];
}
- (UIView *)backView {
if(_backView == nil) {
_backView = [[UIView alloc]initWithFrame:CGRectMake((self.view.frame.size.width - 100) / 2, (self.view.frame.size.height - 100) / 2, 100, 100)];
_backView.backgroundColor = [UIColor clearColor];
_backView.layer.borderColor = [UIColor whiteColor].CGColor;
_backView.layer.borderWidth = 2;
_backView.layer.cornerRadius = self.backView.frame.size.width / 2;
_backView.clipsToBounds = YES;
_backView.hidden = YES;
}
return _backView;
}
- (ShowProgress *)progressView {
if(_progressView == nil) {
_progressView = [[ShowProgress alloc]initWithFrame:CGRectMake((self.view.frame.size.width - 100) / 2, (self.view.frame.size.height - 100) / 2, 100, 100)];
}
return _progressView;
}
- (void)startTask {
//开始
self.backView.hidden = NO;
[self.view addSubview:self.progressView];
_timer = [NSTimer scheduledTimerWithTimeInterval:kMaxTime target:self selector:@selector(taskAction) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSDefaultRunLoopMode];
}
- (void)endTask {
//结束
[_timer invalidate];
_timer = nil;
self.progressView = nil;
[self.progressView removeFromSuperview];
}
- (void)taskAction {
if(_count == kMaxTime) {
[self endTask];
}
[self.progressView setProgress:_count * 0.1];
_count ++;
}
@end
- 关联使用将AFN返回的下载进度对self.progressView 的setProgress:方法,进行填充,既有动画