Show activity indicator in SDWebImage
Asked Answered
W

18

31

I'm using SDWebView image and i want to show an Activity Indicator as placeholder, while fetching the image from remote.

I tried Malek's answer here How to show an activity indicator in SDWebImage, but it seems that

UIImage *cachedImage = [manager imageWithURL:url];

is deprecated.

Is there anyone using this library that could tell me how can i insert an Activity Indicator while loading the image?

EDIT

Following the indications of Michael Frederick, i ended up with this code and everything's working fine.

UIActivityIndicatorView *activityIndicator = [[[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite] autorelease];
activityIndicator.hidesWhenStopped = YES;
activityIndicator.hidden = NO;
[activityIndicator startAnimating];
activityIndicator.center = CGPointMake(self.tipImage.frame.size.width /2, self.tipImage.frame.size.height/2);
[imageView setImageWithURL:[NSURL URLWithString:imageString]
          placeholderImage:nil options:SDWebImageProgressiveDownload
                   success:^(UIImage *image) { [activityIndicator stopAnimating];[activityIndicator removeFromSuperview]; }
                   failure:^(NSError *error) {  [activityIndicator stopAnimating];[activityIndicator removeFromSuperview]; }];

[imageView addSubview:activityIndicator];
Workwoman answered 29/6, 2012 at 12:56 Comment(3)
Did you get it working with the placeholder image?Hyperphagia
I opted to have only a spinner instead of the image, and yes it worked!Workwoman
@Pheel please don't add the answer within the question, add a separate answer (you can answer your own questions). SO format is question+answer(s).Greave
P
47

This fork has support for this functionality. Take a look at the diff.

But, in general, you can do it rather easily without using that fork:

__block UIActivityIndicatorView *activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:activityStyle];
activityIndicator.center = imageView.center;
activityIndicator.hidesWhenStopped = YES;
[imageView setImageWithURL:[NSURL URLWithString:@"http://www.domain.com/path/to/image.jpg"]
               placeholderImage:[UIImage imageNamed:@"placeholder.png"]
                        success:^(UIImage *image) { [activityIndicator removeFromSuperview]; }
                        failure:^(NSError *error) { [activityIndicator removeFromSuperview]; }];

[imageView addSubview:activityIndicator];
[activityIndicator startAnimating];
Pentecostal answered 1/7, 2012 at 16:49 Comment(5)
Thanks, i already checked them out, but something wasn't clear: should i use it WITH or WITHOUT the placeholder? Because that wasn't working! Where should that snippet go into?Workwoman
It might work with the placeholder if you add the activityIndicator after you do 'setImageWithURL'. The snippet should go wherever you would normally set the imageView's image.Pentecostal
Unfortunately it's not working. It loads the placeholder etc but not the activityIndicatorWorkwoman
For comments above mentioning this solution is not working: You need to add this line after your addSubview: [activityIndicator startAnimating];Olympia
When should we stop animating? It is working but also it is not stopping after the image is loaded.Tirol
A
22

This is how you do it:

[imageView setIndicatorStyle:UIActivityIndicatorViewStyleWhite];
[imageView setShowActivityIndicatorView:true];
[imageView sd_setImageWithURL:[NSURL URLWithString:imageUrl] placeholderImage:[UIImage imageNamed:@"defaultl_image"]];
Apartheid answered 22/7, 2015 at 10:19 Comment(4)
I confirm this is the current best solution, since the main repository added finally the activity indicator feature in this commit : github.com/rs/SDWebImage/commit/…Codd
@SourabhSharma This not best coz you need to write 3 lines of code for the same functionality. Which also not a good practice.Forgo
@DeepakChaudhary Ok, then what is the best way to show indicator?Propylene
@SourabhSharma Create an extension of imageView or override init method of imageview then use these two lines. By this, you have to write these only once for the entire app. :)Forgo
C
17

That's my solution. In that file : UIImageView+WebCache.m

Find that method and change like that:

- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder
{
    UIActivityIndicatorView *activity = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:(UIActivityIndicatorViewStyleGray)];
    [activity startAnimating];
    [activity setFrame:CGRectMake(self.frame.origin.x - 20, self.frame.origin.y - 10, self.frame.size.width, self.frame.size.height)];
    [self addSubview:activity];

    //[self setImageWithURL:url placeholderImage:placeholder options:0 progress:nil completed:nil];

    [self setImageWithURL:url
         placeholderImage:placeholder
                  options:0
                completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType)
     {
             [activity removeFromSuperview];
     }];
}
Collings answered 16/7, 2013 at 14:15 Comment(1)
Worked perfectly. You can also add it with a new name, keeping the original.Jedjedd
H
15

Last solution

You can download UIActivityIndicator-for-SDWebImage, which is easiest way to add a UIActivityView to your SDWebImage view. Using CocoaPods, just add this line to your podfile:

pod 'UIActivityIndicator-for-SDWebImage'

You can use one of these lines depending on your preferences:

- (void)setImageWithURL:(NSURL *)url usingActivityIndicatorStyle:(UIActivityIndicatorViewStyle)activityStyle;
- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder usingActivityIndicatorStyle:(UIActivityIndicatorViewStyle)activityStyle;
- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options usingActivityIndicatorStyle:(UIActivityIndicatorViewStyle)activityStyle;
- (void)setImageWithURL:(NSURL *)url completed:(SDWebImageCompletionBlock)completedBlock usingActivityIndicatorStyle:(UIActivityIndicatorViewStyle)activityStyle;
- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletionBlock)completedBlock usingActivityIndicatorStyle:(UIActivityIndicatorViewStyle)activityStyle;
- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock usingActivityIndicatorStyle:(UIActivityIndicatorViewStyle)activityStyle;
- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock usingActivityIndicatorStyle:(UIActivityIndicatorViewStyle)activityStyle;

Example of Use

Just import

#import <UIActivityIndicator-for-SDWebImage/UIImageView+UIActivityIndicatorForSDWebImage.h>

and use this code

[imageView setImageWithURL:[NSURL URLWithString:@"https://media.licdn.com/mpr/mpr/wc_200_200/p/1/005/07f/0a3/30cb8dd.jpg"] placeholderImage:[UIImage imageNamed:@"myImage.jpg"] usingActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
Hustler answered 2/10, 2014 at 14:43 Comment(1)
Indeed! Back in the day there wasn't this solution. But +1 for newer solution!Workwoman
P
7

SDWebImage has a built in Acitvity Indicator that works perfectly. Try this:

Updates: SWIFT 5 SDWebImage 5.x.x

        imgView.sd_imageIndicator = SDWebImageActivityIndicator.gray
        imgView.sd_setImage(with: url, placeholderImage: UIImage(named: "placeholder"))

Swift 3:

imgView.setShowActivityIndicator(true)
imgView.setIndicatorStyle(.gray)
imgView.sd_setImage(with: URL(string: urlString), placeholderImage: UIImage(named: "placeholder"))
Papa answered 24/2, 2017 at 5:29 Comment(0)
E
6

For Swift 5.0 and SDWebImage 5.0 :

Replace

imageView.sd_setShowActivityIndicatorView(true)
imageView.sd_setIndicatorStyle(.gray)

By

imageView.sd_imageIndicator = SDWebImageActivityIndicator.gray
Elliotelliott answered 3/5, 2019 at 8:14 Comment(0)
A
5

The above code is slightly wrong. The line 'activityIndicator.center = imageView.center' does not give you the correct coordinates to center the progress view. For me, it was showing the indicator below the cell.

Note - I am using the latest version of the SDWebImage code so the method is slightly different. I am also using a UIButton for the imageView

Try this:

NSURL *url = [NSURL URLWithString:@"www.someimageurl.com"];
__block UIActivityIndicatorView *activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
activityIndicator.frame = cell.imageView.bounds;
[cell.imageView addSubview:activityIndicator];
[activityIndicator startAnimating];
[cell.imageView setImageWithURL:url forState:UIControlStateNormal completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType) {
    [activityIndicator removeFromSuperview];
}];
Adrianople answered 13/3, 2013 at 22:3 Comment(1)
I've been using the same code as you and the activityIndicator will show for a second then immediatley disappear. I've commented the line that says remove it... Nothing I try will make it stay. It just shows up then promptly disappears. :(Worthwhile
W
5

I believe with the latest version of sdwebimage this is a better method.

[self.customImageView setImageWithURL:imageURL
                             placeholderImage:nil
                                      options:nil
                                     progress:^(NSUInteger receivedSize, long long expectedSize) { [self.activityIndicator startAnimating]; }
                                    completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType) { [self.activityIndicator stopAnimating]; }];

Note: If you don't have a property setup obviously self.activityindicator won't work.

I would use Michael Frederick's example to create the activityindicator instead.

Worthwhile answered 27/3, 2013 at 14:18 Comment(0)
G
3

Same code as above in SWIFT 4:

let activityIndicator = UIActivityIndicatorView.init(activityIndicatorStyle: UIActivityIndicatorViewStyle.gray)
    activityIndicator.center = addImage.center
    activityIndicator.hidesWhenStopped = true

    addImage.sd_setImage(with: URL(string: feed.image), completed: { (image: UIImage?, error: Error?, cacheType: SDImageCacheType, imageURL: URL?) in
        activityIndicator.removeFromSuperview()
    })

    addImage.addSubview(activityIndicator)
    activityIndicator.startAnimating()
Gramnegative answered 20/2, 2018 at 17:1 Comment(0)
D
3

SdWebImage 5.0

YOUR_IMAGEVIEW.sd_imageIndicator = SDWebImageActivityIndicator.gray
Demolition answered 30/4, 2019 at 5:51 Comment(0)
A
2
[cell.dreamImageView setImageWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@",dream.thumbnail]] placeholderImage:[UIImage imageNamed:@"dream_bg_2.png"] options:0 progress:^(NSInteger receivedSize, NSInteger expectedSize) {

    CGFloat domandeFloat = [[NSNumber numberWithInt: receivedSize] floatValue];
    CGFloat corretteFloat = [[NSNumber numberWithInt: expectedSize] floatValue];


    float currentProgress = domandeFloat/corretteFloat;

     NSLog(@"progress %f",currentProgress);
    cell.progressView.progress = currentProgress;

    //[self.dreamsTableView reloadData];


} completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType) {

    cell.progressView.hidden = YES;
}];
Acima answered 31/12, 2014 at 11:28 Comment(1)
Why my expectedSize is 0 on some images?Brusquerie
P
2

Solution updated for Swift 2.0 for using SDWebImage to load image URL

imageView.setShowActivityIndicatorView(true)

imageView.setIndicatorStyle(.White)
Propylene answered 2/11, 2015 at 9:19 Comment(0)
A
1

Based on Can Ürek's answer you might wanna create a category to make it easier to use across multiple applications and without modify SDWebImage framework.

Header file:

#import <UIKit/UIKit.h>

#import <SDWebImage/UIImageView+WebCache.h>

@interface UIImageView (WebCacheWithActivityIndicator)

- (void)setImageShowingActivityIndicatorWithURL:(NSURL *)url completed:(SDWebImageCompletedBlock)completedBlock;

@end

Implementation file:

#import "UIImageView+WebCacheWithActivityIndicator.h"

@implementation UIImageView (WebCacheWithActivityIndicator)

- (void)setImageShowingActivityIndicatorWithURL:(NSURL *)url completed:(SDWebImageCompletedBlock)completedBlock
{
    UIActivityIndicatorView* activityIndication = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];

    [activityIndication setFrame:CGRectMake((self.frame.size.width - activityIndication.frame.size.width) / 2 , (self.frame.size.height - activityIndication.frame.size.height) / 2 , activityIndication.frame.size.width , activityIndication.frame.size.width)];
    [self addSubview:activityIndication];

    [activityIndication startAnimating];

    [self setImageWithURL:url completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType) {

        if(completedBlock)
        {
            completedBlock(image,error,cacheType);
        }

        [activityIndication stopAnimating];
        [activityIndication removeFromSuperview];
    }];
}
@end

Hope it helps you out guys

Cheers

Aerophone answered 20/2, 2014 at 21:46 Comment(0)
S
0

Another solution is to use an animated image as the placeholder image by using:

[UIImage animatedImageNamed:@"animated_placeholder" duration:1]

Salomon answered 26/4, 2014 at 21:43 Comment(0)
R
0

With updated library (Resolved Crash on iOS 8), we have below method -

- (void)sd_setImageWithURL:(NSURL *)url 
{
    [self sd_setImageWithURL:url placeholderImage:nil options:0 progress:nil completed:nil];
}

As we can see the option to add progress block and completed block, we can simply add Activity indicator in progress block and remove in completion block.

Customized method to add Activity Indicator here -

- (void)sd_setImageWithURL:(NSURL *)url {

    [self sd_setImageWithURL:url placeholderImage:nil options:0 progress:^(NSInteger receivedSize, NSInteger expectedSize) {
        UIActivityIndicatorView *activity = nil;
        activity = (UIActivityIndicatorView *)[self viewWithTag:100000];
        if (!activity) {
            activity = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
            [activity setTag:100000];
            [activity setHidesWhenStopped:YES];
            [activity setCenter:CGPointMake(self.frame.size.width/2.0f,self.frame.size.height/2.0f)];
            [self addSubview:activity];
        }
        else {
            [activity setCenter:CGPointMake(self.frame.size.width/2.0f,self.frame.size.height/2.0f)];
        }
        [activity startAnimating];

    } completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
        UIActivityIndicatorView *activity = (UIActivityIndicatorView *)[self viewWithTag:100000];
        if ([activity isKindOfClass:[UIActivityIndicatorView class]]) {
            [activity stopAnimating];
        }
    }];
}

This will add UIActivityIndicatorView to the center of UIImageView when image downloading in progress and remove on completion.

Rosas answered 16/6, 2015 at 7:3 Comment(0)
U
0

My list is quite lag when the user scrolling the list up and down repeatedly. I found out that the activityindicator had been added infinitely when the cellForItemAtIndexPath is being repeatedly called.

To solve this, add a tag at your activityindicator:

activityIndicator.tag = 9999;

Before the UIActivityIndicator is being created, add these lines to remove the previous activityindicator before adding the new one:

UIView* toDeleteLoader = [cell viewWithTag:9999];
if(toDeleteLoader != nil){
    [toDeleteLoader removeFromSuperview];
}

Note: tag content can be any numbers that it won't be used in your cell.

Unwatched answered 16/7, 2015 at 4:37 Comment(0)
J
0

Best solution that worked for me is below. It is beautiful and encouraging to show progress indicator when image is downloading. I used UICircularSlider as rounded progress view. You can also try it.

    [_imgPost sd_setImageWithURL:urlPost placeholderImage:zeroImage options:SDWebImageContinueInBackground progress:^(NSInteger receivedSize, NSInteger expectedSize)
    {
        CGFloat domandeFloat = [[NSNumber numberWithInteger: receivedSize] floatValue];
        CGFloat corretteFloat = [[NSNumber numberWithInteger: expectedSize] floatValue];


        float currentProgress = (domandeFloat/corretteFloat)*100;

        NSLog(@"progress %.f%%",currentProgress);
        DBG(@"%li, %li", receivedSize, expectedSize);
        [_progress setValue:currentProgress];
    } completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {

        [_progress setHidden:YES];
    }];

Here _progress is an instance of UICircularSlider

Junco answered 26/3, 2016 at 19:20 Comment(0)
N
0

SDWebImage 5.0 has support of displaying activity indicator using SDWebImageActivityIndicator class.

let imageView = UIImageView()
imageView.sd_imageIndicator = SDWebImageActivityIndicator.gray
Noletta answered 25/9, 2020 at 8:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.