From 2cfa5ccb883191df510ad15df2a97a765b9d5e82 Mon Sep 17 00:00:00 2001 From: mythodeia Date: Thu, 6 Nov 2014 19:26:44 +0200 Subject: [PATCH] Loading Indicator view with 2 lines of code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit added support for UIActivityIndicatorView while the image is downloaded, without adding extra ‘setImageWithUrl’ methods to the UIImageView+WebCache category. I used [this pull request](https://github.com/mythodeia/UIActivityIndicator-for-SDWebImage ), original author is [JJSaccolo](https://github.com/JJSaccolo), and modded it a bit to support loading indicator while the image is downloading. the usage is basically this right before the usual sd_setImage... methods: ``` // show activity indicator [cell.imageView setShowActivityIndicatorView:YES]; // choose indicator style [cell.imageView setIndicatorStyle:UIActivityIndicatorViewStyleGray]; ``` --- .../SDWebImage Demo/MasterViewController.m | 4 ++ SDWebImage/UIImageView+WebCache.h | 12 ++++ SDWebImage/UIImageView+WebCache.m | 72 ++++++++++++++++++- 3 files changed, 85 insertions(+), 3 deletions(-) diff --git a/Examples/SDWebImage Demo/MasterViewController.m b/Examples/SDWebImage Demo/MasterViewController.m index daf90c5..b72b7d9 100644 --- a/Examples/SDWebImage Demo/MasterViewController.m +++ b/Examples/SDWebImage Demo/MasterViewController.m @@ -377,6 +377,10 @@ if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; + // show activity indicator + [cell.imageView setShowActivityIndicatorView:YES]; + // choose indicator style + [cell.imageView setIndicatorStyle:UIActivityIndicatorViewStyleGray]; } cell.textLabel.text = [NSString stringWithFormat:@"Image #%ld", (long)indexPath.row]; diff --git a/SDWebImage/UIImageView+WebCache.h b/SDWebImage/UIImageView+WebCache.h index 50de8c5..ce1d834 100644 --- a/SDWebImage/UIImageView+WebCache.h +++ b/SDWebImage/UIImageView+WebCache.h @@ -176,4 +176,16 @@ - (void)sd_cancelCurrentAnimationImagesLoad; +/** + * Show activity UIActivityIndicatorView + */ +- (void)setShowActivityIndicatorView:(BOOL)show; + +/** + * set desired UIActivityIndicatorViewStyle + * + * @param style The style of the UIActivityIndicatorView + */ +- (void)setIndicatorStyle:(UIActivityIndicatorViewStyle)style; + @end diff --git a/SDWebImage/UIImageView+WebCache.m b/SDWebImage/UIImageView+WebCache.m index 440613b..7867f09 100644 --- a/SDWebImage/UIImageView+WebCache.m +++ b/SDWebImage/UIImageView+WebCache.m @@ -11,6 +11,9 @@ #import "UIView+WebCacheOperation.h" static char imageURLKey; +static char TAG_ACTIVITY_INDICATOR; +static char TAG_ACTIVITY_STYLE; +static char TAG_ACTIVITY_SHOW; @implementation UIImageView (WebCache) @@ -47,13 +50,19 @@ static char imageURLKey; self.image = placeholder; }); } - + + // check if activityView is enabled or not + if ([self showActivityIndicatorView]) { + [self addActivityIndicator]; + } + if (url) { __weak UIImageView *wself = self; id operation = [SDWebImageManager.sharedManager downloadImageWithURL:url options:options progress:progressBlock completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { if (!wself) return; dispatch_main_sync_safe(^{ if (!wself) return; + [wself removeActivityIndicator]; if (image) { wself.image = image; [wself setNeedsLayout]; @@ -71,6 +80,7 @@ static char imageURLKey; [self sd_setImageLoadOperation:operation forKey:@"UIImageViewImageLoad"]; } else { dispatch_main_async_safe(^{ + [self removeActivityIndicator]; NSError *error = [NSError errorWithDomain:@"SDWebImageErrorDomain" code:-1 userInfo:@{NSLocalizedDescriptionKey : @"Trying to load a nil url"}]; if (completedBlock) { completedBlock(nil, error, SDImageCacheTypeNone, url); @@ -82,8 +92,8 @@ static char imageURLKey; - (void)sd_setImageWithPreviousCachedImageWithURL:(NSURL *)url andPlaceholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock { NSString *key = [[SDWebImageManager sharedManager] cacheKeyForURL:url]; UIImage *lastPreviousCachedImage = [[SDImageCache sharedImageCache] imageFromDiskCacheForKey:key]; - - [self sd_setImageWithURL:url placeholderImage:lastPreviousCachedImage ?: placeholder options:options progress:progressBlock completed:completedBlock]; + + [self sd_setImageWithURL:url placeholderImage:lastPreviousCachedImage ?: placeholder options:options progress:progressBlock completed:completedBlock]; } - (NSURL *)sd_imageURL { @@ -129,4 +139,60 @@ static char imageURLKey; [self sd_cancelImageLoadOperationWithKey:@"UIImageViewAnimationImages"]; } +- (UIActivityIndicatorView *)activityIndicator { + return (UIActivityIndicatorView *)objc_getAssociatedObject(self, &TAG_ACTIVITY_INDICATOR); +} +- (void)setActivityIndicator:(UIActivityIndicatorView *)activityIndicator { + objc_setAssociatedObject(self, &TAG_ACTIVITY_INDICATOR, activityIndicator, OBJC_ASSOCIATION_RETAIN); +} + +- (void)setShowActivityIndicatorView:(BOOL)show{ + objc_setAssociatedObject(self, &TAG_ACTIVITY_SHOW, [NSNumber numberWithBool:show], OBJC_ASSOCIATION_RETAIN); +} +- (BOOL)showActivityIndicatorView{ + return [objc_getAssociatedObject(self, &TAG_ACTIVITY_SHOW) boolValue]; +} + +- (void)setIndicatorStyle:(UIActivityIndicatorViewStyle)style{ + objc_setAssociatedObject(self, &TAG_ACTIVITY_STYLE, [NSNumber numberWithInt:style], OBJC_ASSOCIATION_RETAIN); +} +- (int)getIndicatorStyle{ + return [objc_getAssociatedObject(self, &TAG_ACTIVITY_STYLE) intValue]; +} + +- (void)addActivityIndicator { + if (!self.activityIndicator) { + self.activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:[self getIndicatorStyle]]; + self.activityIndicator.autoresizingMask = UIViewAutoresizingNone; + + dispatch_async(dispatch_get_main_queue(), ^(void) { + [self addSubview:self.activityIndicator]; + [self updateActivityIndicatorFrame]; + }); + } + + dispatch_async(dispatch_get_main_queue(), ^(void) { + [self.activityIndicator startAnimating]; + }); + +} +- (void)updateActivityIndicatorFrame { + if (self.activityIndicator) { + CGRect activityIndicatorBounds = self.activityIndicator.bounds; + float x = (self.frame.size.width - activityIndicatorBounds.size.width) / 2.0; + float y = (self.frame.size.height - activityIndicatorBounds.size.height) / 2.0; + self.activityIndicator.frame = CGRectMake(x, y, activityIndicatorBounds.size.width, activityIndicatorBounds.size.height); + } +} +- (void)removeActivityIndicator { + if (self.activityIndicator) { + [self.activityIndicator removeFromSuperview]; + self.activityIndicator = nil; + } +} +- (void)layoutSubviews { + [super layoutSubviews]; + [self updateActivityIndicatorFrame]; +} + @end