IOS custom control-display the ImageView and iosimageview of the download process
Original Blog, reprinted, please indicate the source
Blog.csdn.net/hello_hwc
The purpose of this series is to provide some ideas. In the Demo process, the readers can learn some ideas about custom controls, so it is not suitable for being too complicated. Of course, this is just a reference. I will upload this control to Github. I have been working on IOT applications recently, so I don't have time to complete it. I will complete it when I have time, let the reader directly use it.
I will update my blog.
Demo effect. Two display methods are supported. Draw a circle along the border and gradually fill the frame.
Ideas
- NSURLSessionDataTask
- Display the download process in Layer mode
Interface Design
Header file source code
#import <UIKit/UIKit.h>typedef NS_ENUM(NSUInteger, WCProgressType) { WCProgressTypeBorder, WCProgressTypeFrame,};typedef void(^WCCompeltionBlock)(UIImage * image,NSError *error);@interface WCProgressImageview : UIImageView@property (nonatomic,getter=currentProgress,readonly)CGFloat progress;@property (nonatomic,strong) NSString * url;@property (nonatomic)WCProgressType type;-(void)resume;-(instancetype)initWithFrame:(CGRect)frame ImageURL:(NSString *)url Type:(WCProgressType)type;-(instancetype)initWithFrame:(CGRect)frame ImageURL:(NSString *)url Type:(WCProgressType)type ComepetionHander:(WCCompeltionBlock)block;@end
1. This parameter must support two types. Therefore, the enumerated values are defined as two types.
2. Define the block to asynchronously pass the imageview loading completion time to the user.
3. Read-only attribute progress to get the current download progress
4. the url and type represent the url and progress bar types of the image respectively.
5. Two APIs are provided to initialize objects.
Implementation
@interface WCProgressImageview()<NSURLSessionDelegate,NSURLSessionDataDelegate>@property (strong,nonatomic)NSMutableData * buffer;@property (nonatomic)NSUInteger expectlength;@property (nonatomic,strong)CALayer * frameProgressLayer;@property (nonatomic,strong)CAShapeLayer * borderProgressLayer;@property (strong,nonatomic)NSURLSessionDataTask * dataTask;@property (strong,nonatomic) NSURLSession * session;@property (nonatomic,strong) WCCompeltionBlock completionBlock;@property (nonatomic,getter=currentProgress,readwrite)CGFloat progress;@end@implementation WCProgressImageview#pragma mark - property-(NSMutableData *)buffer{ if (!_buffer) { _buffer = [[NSMutableData alloc] init]; } return _buffer;}-(CALayer *)frameProgressLayer{ if (!_frameProgressLayer) { _frameProgressLayer = [CALayer layer]; _frameProgressLayer.backgroundColor = [UIColor lightGrayColor].CGColor; _frameProgressLayer.bounds = CGRectMake(0,0,0,CGRectGetHeight(self.frame)); _frameProgressLayer.anchorPoint = CGPointMake(0,0); _frameProgressLayer.position = CGPointMake(0,0); } return _frameProgressLayer;}-(CAShapeLayer *)borderProgressLayer{ if (!_borderProgressLayer) { _borderProgressLayer = [CAShapeLayer layer]; _borderProgressLayer.bounds = CGRectMake(0,0,CGRectGetWidth(self.frame),CGRectGetHeight(self.frame)); _borderProgressLayer.anchorPoint = CGPointMake(0,0); _borderProgressLayer.position = CGPointMake(0,0); _borderProgressLayer.fillColor = [UIColor clearColor].CGColor; _borderProgressLayer.lineWidth = 3.0; _borderProgressLayer.path = [UIBezierPath bezierPathWithRoundedRect:_borderProgressLayer.bounds cornerRadius:10.0].CGPath; _borderProgressLayer.strokeColor = [UIColor blueColor].CGColor; _borderProgressLayer.strokeStart = 0.0; _borderProgressLayer.strokeEnd = 0.0; } return _borderProgressLayer;}-(CGPathRef)createPathWith:(CGPoint *)center Radius:(CGFloat)radius Progress:(CGFloat)progress{ CGMutablePathRef mutablepath = CGPathCreateMutable(); return mutablepath;}-(NSURLSession *)session{ if (!_session) { _session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]]; } return _session;}-(void)setUrl:(NSString *)url{ self.progress = 0; self.dataTask = [self.session dataTaskWithURL:[NSURL URLWithString:url]];}#pragma mark - API-(instancetype)initWithFrame:(CGRect)frame ImageURL:(NSString *)url Type:(WCProgressType)type{ if (self = [super initWithFrame:frame]) { self.url = url; self.type = type; self.progress = 0; } return self;}-(instancetype)initWithFrame:(CGRect)frame ImageURL:(NSString *)url Type:(WCProgressType)type ComepetionHander:(WCCompeltionBlock)block{ if (self = [super initWithFrame:frame]) { self.url = url; self.completionBlock = block; self.type = type; self.progress = 0; } return self;}-(void)resume{ [self.dataTask resume]; switch (self.type) { case WCProgressTypeFrame: [self.layer addSublayer:self.frameProgressLayer]; break; case WCProgressTypeBorder: [self.layer addSublayer:self.borderProgressLayer]; break; default: break; }}#pragma mark - URLSessionDelegate-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler{ NSHTTPURLResponse * httpresponse = (NSHTTPURLResponse *)response; self.expectlength = [httpresponse expectedContentLength]; completionHandler(NSURLSessionResponseAllow);}-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data{ [self.buffer appendData:data]; self.progress = self.buffer.length/(double)self.expectlength; NSLog(@"%f",self.progress); if (self.expectlength > 0) { switch (self.type) { case WCProgressTypeFrame: self.frameProgressLayer.bounds = CGRectMake(0,0,CGRectGetWidth(self.frame) * self.progress,CGRectGetHeight(self.frame)); break; case WCProgressTypeBorder: self.borderProgressLayer.strokeEnd = self.progress; break; default: break; } }}-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{ [self.frameProgressLayer removeFromSuperlayer]; self.frameProgressLayer = nil; [self.borderProgressLayer removeFromSuperlayer]; self.borderProgressLayer = nil; if (!error) { UIImage * image = [UIImage imageWithData:self.buffer]; self.image = image; if (self.completionBlock) { self.completionBlock(image,error); } }else { self.completionBlock(nil,error); } [self clean];}-(void)clean{ self.buffer = nil; [self.session invalidateAndCancel]; self.session = nil;}@end
Explanations
1. Attribute initialization using inertia
2. Use the StrokeEnd attribute of CAShape Layer to represent the progress.
3. Use NSURLSessionDelegate and NSURLSessionDataDelegate to obtain data and progress.
Use
self.imageview1 = [[WCProgressImageview alloc] initWithFrame:CGRectMake(40,40,300,200) ImageURL:@"http://f12.topit.me/o129/10129120625790e866.jpg" Type:WCProgressTypeBorder ComepetionHander:^(UIImage *image, NSError *error) { }]; [self.imageview1 resume]; [self.view addSubview:self.imageview1];