| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297 |
- //
- // UIImageView+XHURLDownload.m
- // XHImageViewer
- //
- // Created by 曾 宪华 on 14-2-18.
- // Copyright (c) 2014年 曾宪华 开发团队(http://iyilunba.com ) 本人QQ:543413507 本人QQ群(142557668). All rights reserved.
- //
- #import "UIImageView+XHURLDownload.h"
- #import <objc/runtime.h>
- #import "XHCacheManager.h"
- const char* const kXHURLPropertyKey = "XHURLDownloadURLPropertyKey";
- const char* const kXHLoadingStateKey = "XHURLDownloadLoadingStateKey";
- const char* const kXHLoadingViewKey = "XHURLDownloadLoadingViewKey";
- const char* const kXHActivityIndicatorViewKey = "XHActivityIndicatorViewKey";
- #define kXHActivityIndicatorViewSize 35
- @implementation UIImageView (XHURLDownload)
- + (id)imageViewWithURL:(NSURL *)url autoLoading:(BOOL)autoLoading {
- UIImageView *view = [self new];
- view.url = url;
- if(autoLoading) {
- [view load];
- }
- return view;
- }
- + (id)indicatorImageView {
- UIImageView *view = [self new];
- [view setDefaultLoadingView];
-
- return view;
- }
- + (id)indicatorImageViewWithURL:(NSURL *)url autoLoading:(BOOL)autoLoading {
- UIImageView *view = [self imageViewWithURL:url autoLoading:autoLoading];
- [view setDefaultLoadingView];
-
- return view;
- }
- #pragma mark- Properties
- - (dispatch_queue_t)cachingQueue {
- static dispatch_queue_t cachingQeueu;
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken, ^{
- cachingQeueu = dispatch_queue_create("caching image and data", NULL);
- });
- return cachingQeueu;
- }
- - (void)setActivityIndicatorView:(UIActivityIndicatorView *)activityIndicatorView {
- objc_setAssociatedObject(self, kXHActivityIndicatorViewKey, activityIndicatorView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
- }
- - (UIActivityIndicatorView *)activityIndicatorView {
- return objc_getAssociatedObject(self, kXHActivityIndicatorViewKey);
- }
- - (NSURL*)url {
- return objc_getAssociatedObject(self, kXHURLPropertyKey);
- }
- - (void)setUrl:(NSURL *)url {
- [self setUrl:url autoLoading:NO];
- }
- - (void)setUrl:(NSURL *)url autoLoading:(BOOL)autoLoading {
- if(![url isEqual:self.url]) {
- objc_setAssociatedObject(self, kXHURLPropertyKey, url, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
-
- if (url) {
- self.loadingState = UIImageViewURLDownloadStateWaitingForLoad;
- }
- else {
- self.loadingState = UIImageViewURLDownloadStateUnknown;
- }
- }
-
- if(autoLoading) {
- [self load];
- }
- }
- - (void)loadWithURL:(NSURL *)url {
- [self loadWithURL:url placeholer:nil];
- }
- - (void)loadWithURL:(NSURL *)url placeholer:(UIImage *)placeholerImage {
- [self loadWithURL:url placeholer:placeholerImage showActivityIndicatorView:NO];
- }
- - (void)loadWithURL:(NSURL *)url placeholer:(UIImage *)placeholerImage showActivityIndicatorView:(BOOL)show {
- [self _setupPlaecholerImage:placeholerImage showActivityIndicatorView:show];
- [self setUrl:url autoLoading:YES];
- }
- - (void)loadWithURL:(NSURL *)url placeholer:(UIImage *)placeholerImage showActivityIndicatorView:(BOOL)show completionBlock:(void(^)(UIImage *image, NSURL *url, NSError *error))handler {
- [self _setupPlaecholerImage:placeholerImage showActivityIndicatorView:show];
- [self setUrl:url autoLoading:NO];
- [self loadWithCompletionBlock:handler];
- }
- - (void)_setupPlaecholerImage:(UIImage *)placeholerImage showActivityIndicatorView:(BOOL)show {
- if (placeholerImage)
- [self setImage:placeholerImage];
- if (show) {
- UIActivityIndicatorView *activityIndicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
- activityIndicatorView.frame = CGRectMake(0, 0, kXHActivityIndicatorViewSize, kXHActivityIndicatorViewSize);
- activityIndicatorView.center = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
- [activityIndicatorView startAnimating];
- [self addSubview:activityIndicatorView];
- [self setActivityIndicatorView:activityIndicatorView];
- }
- }
- - (UIImageViewURLDownloadState)loadingState {
- return (NSUInteger)([objc_getAssociatedObject(self, kXHLoadingStateKey) integerValue]);
- }
- - (void)setLoadingState:(UIImageViewURLDownloadState)loadingState {
- objc_setAssociatedObject(self, kXHLoadingStateKey, @(loadingState), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
- }
- - (UIView *)loadingView {
- return objc_getAssociatedObject(self, kXHLoadingViewKey);
- }
- - (void)setLoadingView:(UIView *)loadingView {
- [self.loadingView removeFromSuperview];
-
- objc_setAssociatedObject(self, kXHLoadingViewKey, loadingView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
-
- loadingView.center = CGPointMake(self.frame.size.width / 2, self.frame.size.height / 2);
- loadingView.alpha = 0;
- [self addSubview:loadingView];
- }
- - (void)setDefaultLoadingView {
- UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
- indicator.frame = self.frame;
- indicator.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
- indicator.backgroundColor = [UIColor colorWithWhite:0.9 alpha:1];
- self.loadingView = indicator;
- }
- #pragma mark- Loading view
- - (void)showLoadingView {
- dispatch_async(dispatch_get_main_queue(), ^{
- self.loadingView.alpha = 1;
- if([self.loadingView respondsToSelector:@selector(startAnimating)]) {
- [self.loadingView performSelector:@selector(startAnimating)];
- }
- });
- }
- - (void)hideLoadingView {
- dispatch_async(dispatch_get_main_queue(), ^{
- UIActivityIndicatorView *activityIndicatorView = [self activityIndicatorView];
- if (activityIndicatorView) {
- [activityIndicatorView stopAnimating];
- [activityIndicatorView removeFromSuperview];
- }
- [UIView animateWithDuration:0.3
- animations:^{
- self.loadingView.alpha = 0;
- }
- completion:^(BOOL finished) {
- if([self.loadingView respondsToSelector:@selector(stopAnimating)]) {
- [self.loadingView performSelector:@selector(stopAnimating)];
- }
- }
- ];
- });
- }
- #pragma mark- Image downloading
- + (NSOperationQueue *)downloadQueue {
- static NSOperationQueue *_sharedQueue = nil;
-
- if(_sharedQueue == nil) {
- _sharedQueue = [NSOperationQueue new];
- [_sharedQueue setMaxConcurrentOperationCount:3];
- }
-
- return _sharedQueue;
- }
- + (void)dataWithContentsOfURL:(NSURL *)url completionBlock:(void (^)(NSURL *, NSData *, NSError *))completion {
-
- NSURLRequest *request = [NSURLRequest requestWithURL:url];
- NSURLSession *session = [NSURLSession sharedSession];
- NSURLSessionDataTask *task = [session dataTaskWithRequest:request
- completionHandler:
- ^(NSData *data, NSURLResponse *response, NSError *error) {
- if(completion) {
- completion(url, data, error);
- }
- }];
- [task resume];
-
-
- /*
- NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
- [request setHTTPMethod:@"GET"];
- [request setTimeoutInterval:5.0];
-
- [NSURLConnection sendAsynchronousRequest:request
- queue:[self downloadQueue]
- completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
- if(completion) {
- completion(url, data, connectionError);
- }
- }
- ];
- */
- }
- - (void)load {
- [self loadWithCompletionBlock:nil];
- }
- - (void)loadWithCompletionBlock:(void(^)(UIImage *image, NSURL *url, NSError *error))handler {
- self.loadingState = UIImageViewURLDownloadStateNowLoading;
-
- [self showLoadingView];
-
- __weak typeof(self) weakSelf = self;
- dispatch_async(self.cachingQueue, ^{
- UIImage *cacheImage = [XHCacheManager imageWithURL:weakSelf.url storeMemoryCache:YES];
- if (cacheImage) {
- [self setImage:cacheImage forURL:weakSelf.url];
- if (handler)
- handler(cacheImage, weakSelf.url, nil);
- } else {
- // It could be more better by replacing with a method that has delegates like a progress.
- [UIImageView dataWithContentsOfURL:weakSelf.url
- completionBlock:^(NSURL *url, NSData *data, NSError *error) {
- UIImage *image = [weakSelf didFinishDownloadWithData:data forURL:url error:error];
-
- if(handler) {
- handler(image, url, error);
- }
- }
- ];
- }
- });
- }
- - (void)cachingImageData:(NSData *)imageData url:(NSURL *)url {
- dispatch_async(self.cachingQueue, ^{
- if (imageData) {
- [XHCacheManager storeData:imageData forURL:url storeMemoryCache:NO];
- UIImage *image = [UIImage imageWithData:imageData];
- if (image)
- [XHCacheManager storeMemoryCacheWithImage:image forURL:url];
- }
- });
- }
- - (UIImage *)didFinishDownloadWithData:(NSData *)data forURL:(NSURL *)url error:(NSError *)error {
- if (data) {
- [self cachingImageData:data url:url];
- }
- UIImage *image = [UIImage imageWithData:data];
- if([url isEqual:self.url]) {
- if(error) {
- self.loadingState = UIImageViewURLDownloadStateFailed;
- }
- else {
- [self performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:NO];
- self.loadingState = UIImageViewURLDownloadStateLoaded;
- }
- [self hideLoadingView];
- }
- return image;
- }
- - (void)setImage:(UIImage *)image forURL:(NSURL *)url {
- if([url isEqual:self.url]) {
- [self performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:NO];
- self.loadingState = UIImageViewURLDownloadStateLoaded;
- [self hideLoadingView];
- }
- }
- @end
|