3

I have a horizontal collection view and it has 20 cells with UIImageView I just want to show the activity indicator till the image download completed. I am using the new SDWebImage library where we have methods as sd_setImageWithURL Till now What i am doing is

__block UIActivityIndicatorView *activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
activityIndicator.center = cell.photoOneImageView.center;
activityIndicator.hidesWhenStopped = YES;

[cell.photoOneImageView sd_setImageWithURL:[NSURL URLWithString:@"https://scontent-sjc.xx.fbcdn.net/hphotos-xpa1/v/t1.0-9/p480x480/11073324_10153728863852926_4010319763478440264_n.jpg?oh=590934059508b7da235a46fc39e08063&oe=55B61458"] 
placeholderImage:[UIImage imageNamed:@"placeholder.jpg"] 
completed:^(UIImage *image, NSError *error,  SDImageCacheType cacheType, NSURL *imageURL) {
    [activityIndicator stopAnimating];
    [activityIndicator removeFromSuperview];
    }];

[cell.photoOneImageView addSubview:activityIndicator];
[activityIndicator startAnimating];

I am writing this code in cellForItemAtIndexPath method It shows sometimes multiple indicators on 1 cell and they are not removing also sometimes when we scroll the collection view horizontally.

I saw this https://github.com/rs/SDNetworkActivityIndicator but I am unable to use this. No luck with that. Has anyone implemented activity indicator in tebleview cell or collection view cell when the image completed the indicator vanish. Please help. Any help will be appreciated. Thanks

Rajan Maheshwari
  • 14,465
  • 6
  • 64
  • 98

5 Answers5

5

Best way is to use SDWebImage's default activity indicator available in the latest repo

Updates: SWIFT 5 SDWebImage 5.x.x

        cell.imageView.sd_imageIndicator = SDWebImageActivityIndicator.gray
        cell.imageView.sd_setImage(with: url) { (image, error, cache, urls) in
            if (error != nil) {
                // Failed to load image
                cell.imageView.image = UIImage(named: "ico_placeholder")
            } else {
                // Successful in loading image
                cell.imageView.image = image
            }
        }

swift 3 :

cell.imageView.setShowActivityIndicator(true)
cell.imageView.setIndicatorStyle(.gray)
cell.imageView?.sd_setImage(with: url) { (image, error, cache, urls) in
                if (error != nil) {
                    // Failed to load image
                    cell.imageView.image = UIImage(named: "ico_placeholder")
                } else {
                    // Successful in loading image
                    cell.imageView.image = image
                }
 }
Ankit Kumar Gupta
  • 3,994
  • 4
  • 31
  • 54
2

The issue you are having is that you are adding a UIActivityIndicatorView on a cell that might get dequed and reused later on before your block triggers.

To fix this, make the activity indicator a property of your cell:

@interface Cell : UICollectionViewCell

@property (strong, nonatomic) UIActivityIndicatorView activityIndicator;

@end

Then, your implementation should look like this:

@implementation Cell

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self initialize];
    }
    return self;
}

- (void)awakeFromNib
{
    [super awakeFromNib];
    [self initialize];
}

- (void)initialize
{
    // This code is only called once
    self.activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
    self.activityIndicator.center = self.photoOneImageView.center;
    self.activityIndicator.hidesWhenStopped = YES;
    [self.photoOneImageView addSubview:self.activityIndicator];
}

@end

Then:

[cell.photoOneImageView sd_setImageWithURL:[NSURL URLWithString:@"https://somesite.com/pic.jpg"] 
                          placeholderImage:[UIImage imageNamed:@"placeholder.jpg"] 
                                 completed:
    ^(UIImage *image, NSError *error,  SDImageCacheType cacheType, NSURL *imageURL) {
        [cell.activityIndicator stopAnimating];
    }];

[cell.activityIndicator startAnimating];
Pedro Mancheno
  • 5,237
  • 4
  • 24
  • 31
0

You can use the library https://github.com/JJSaccolo/UIActivityIndicator-for-SDWebImage to fix the issue.

Very simple to load image with an activity indicator

[cell.photoOneImageView setImageWithURL:[NSURL URLWithString:@"https://scontent-sjc.xx.fbcdn.net/hphotos-xpa1/v/t1.0-9/p480x480/11073324_10153728863852926_4010319763478440264_n.jpg?oh=590934059508b7da235a46fc39e08063&oe=55B61458"] 
        placeholderImage:[UIImage imageNamed:@"placeholder.jpg"]
    usingActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
Nhu Nguyen
  • 874
  • 3
  • 18
  • 33
0

swift 3 For extension UIImageView+Download+Extension.swift:

import SDWebImage

extension UIImageView {
    func setImageWithIndicator(imageUrl: String, callback: ((_ image: UIImage) -> Void)? = nil) {
        guard !imageUrl.isEmpty else {
            return
    }

        if let url = NSURL(string: imageUrl), url.host != nil {
            self.setShowActivityIndicator(true)
            self.setIndicatorStyle(.gray)
            self.sd_setImage(with: url as URL!, completed: { (_, _, _, _) in
        })
     }
   }
}

using:

UIImageView.setImageWithIndicator(imageUrl: url)
Giang
  • 3,553
  • 30
  • 28
0

you have to create a separate CollectionView cell, to get reused.

or just do this after creating collectionviewcell:

  for (__strong UIView *view in Cell.contentView.subviews) {
if([view isKindofClass: [UIActivityIndicatorView class]]])
{

        [view removeFromSuperview];
        view = nil;}
    }

Because you are always creating new object of activityindicatorView

Ajjjjjjjj
  • 669
  • 4
  • 12