Refactor the image indicator usage for UIView category. Use two protocol `SDWebImageIndicator` & `SDWebImageProgressIndicator` to make this more customizable. Implement two class about activity indicator and progress indicator for both UIKit/AppKit

This commit is contained in:
DreamPiggy 2018-01-20 23:40:16 +08:00
parent af282c1d5e
commit e012b36679
9 changed files with 425 additions and 141 deletions

View File

@ -7,64 +7,25 @@
*/
#import "DetailViewController.h"
#import <SDWebImage/FLAnimatedImageView.h>
#import <SDWebImage/UIView+WebCache.h>
#import <SDWebImage/FLAnimatedImageView+WebCache.h>
@interface DetailViewController ()
@property (strong, nonatomic) IBOutlet FLAnimatedImageView *imageView;
@property (strong, nonatomic) UIActivityIndicatorView *activityIndicator;
@property (strong, nonatomic) UIProgressView *progressView;
@end
@implementation DetailViewController
- (UIActivityIndicatorView *)activityIndicator
{
if (!_activityIndicator) {
_activityIndicator = [UIActivityIndicatorView.alloc initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
_activityIndicator.center = self.imageView.center;
_activityIndicator.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
[self.imageView addSubview:_activityIndicator];
}
return _activityIndicator;
}
- (UIProgressView *)progressView
{
if (!_progressView) {
_progressView = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleDefault];
[self.view addSubview:_progressView];
}
return _progressView;
}
- (void)configureView
{
self.activityIndicator.hidden = NO;
[self.activityIndicator startAnimating];
__weak typeof(self) weakSelf = self;
if (!self.imageView.sd_imageIndicator) {
self.imageView.sd_imageIndicator = SDWebImageProgressIndicator.defaultIndicator;
}
[self.imageView sd_setImageWithURL:self.imageURL
placeholderImage:nil
options:SDWebImageProgressiveDownload
progress:^(NSInteger receivedSize, NSInteger expectedSize, NSURL *targetURL) {
dispatch_async(dispatch_get_main_queue(), ^{
float progress = 0;
if (expectedSize != 0) {
progress = (float)receivedSize / (float)expectedSize;
}
weakSelf.progressView.hidden = NO;
[weakSelf.progressView setProgress:progress animated:YES];
});
}
completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
weakSelf.progressView.hidden = YES;
[weakSelf.activityIndicator stopAnimating];
weakSelf.activityIndicator.hidden = YES;
}];
options:SDWebImageProgressiveDownload];
}
- (void)viewDidLoad
@ -73,12 +34,6 @@
[self configureView];
}
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
self.progressView.frame = CGRectMake(0, self.topLayoutGuide.length, CGRectGetWidth(self.view.bounds), 2.0);
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);

View File

@ -118,10 +118,8 @@
if (cell == nil) {
cell = [[MyCustomTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell.customImageView.sd_imageTransition = SDWebImageTransition.fadeTransition;
cell.customImageView.sd_imageIndicator = SDWebImageActivityIndicator.grayIndicator;
}
[cell.customImageView sd_setShowActivityIndicatorView:YES];
[cell.customImageView sd_setIndicatorStyle:UIActivityIndicatorViewStyleGray];
cell.customTextLabel.text = [NSString stringWithFormat:@"Image #%ld", (long)indexPath.row];
[cell.customImageView sd_setImageWithURL:[NSURL URLWithString:self.objects[indexPath.row]]

View File

@ -31,6 +31,7 @@
// For animated GIF rendering, set `animates` to YES or will only show the first frame
self.imageView1.animates = YES;
self.imageView3.animates = YES;
self.imageView1.sd_imageIndicator = SDWebImageProgressIndicator.defaultIndicator;
[self.imageView1 sd_setImageWithURL:[NSURL URLWithString:@"http://assets.sbnation.com/assets/2512203/dogflops.gif"]];
[self.imageView2 sd_setImageWithURL:[NSURL URLWithString:@"http://www.ioncannon.net/wp-content/uploads/2011/06/test2.webp"]];
[self.imageView3 sd_setImageWithURL:[NSURL URLWithString:@"http://littlesvr.ca/apng/images/SteamEngine.webp"]];

View File

@ -362,6 +362,18 @@
329A18621FFF5DFD008C9A2F /* UIImage+WebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 329A18581FFF5DFD008C9A2F /* UIImage+WebCache.m */; };
329A18631FFF5DFD008C9A2F /* UIImage+WebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 329A18581FFF5DFD008C9A2F /* UIImage+WebCache.m */; };
329A18641FFF5DFD008C9A2F /* UIImage+WebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 329A18581FFF5DFD008C9A2F /* UIImage+WebCache.m */; };
32C0FDE12013426C001B8F2D /* SDWebImageIndicator.h in Headers */ = {isa = PBXBuildFile; fileRef = 32C0FDDF2013426C001B8F2D /* SDWebImageIndicator.h */; settings = {ATTRIBUTES = (Public, ); }; };
32C0FDE22013426C001B8F2D /* SDWebImageIndicator.h in Headers */ = {isa = PBXBuildFile; fileRef = 32C0FDDF2013426C001B8F2D /* SDWebImageIndicator.h */; settings = {ATTRIBUTES = (Public, ); }; };
32C0FDE32013426C001B8F2D /* SDWebImageIndicator.h in Headers */ = {isa = PBXBuildFile; fileRef = 32C0FDDF2013426C001B8F2D /* SDWebImageIndicator.h */; settings = {ATTRIBUTES = (Public, ); }; };
32C0FDE42013426C001B8F2D /* SDWebImageIndicator.h in Headers */ = {isa = PBXBuildFile; fileRef = 32C0FDDF2013426C001B8F2D /* SDWebImageIndicator.h */; settings = {ATTRIBUTES = (Public, ); }; };
32C0FDE52013426C001B8F2D /* SDWebImageIndicator.h in Headers */ = {isa = PBXBuildFile; fileRef = 32C0FDDF2013426C001B8F2D /* SDWebImageIndicator.h */; settings = {ATTRIBUTES = (Public, ); }; };
32C0FDE62013426C001B8F2D /* SDWebImageIndicator.h in Headers */ = {isa = PBXBuildFile; fileRef = 32C0FDDF2013426C001B8F2D /* SDWebImageIndicator.h */; settings = {ATTRIBUTES = (Public, ); }; };
32C0FDE72013426C001B8F2D /* SDWebImageIndicator.m in Sources */ = {isa = PBXBuildFile; fileRef = 32C0FDE02013426C001B8F2D /* SDWebImageIndicator.m */; };
32C0FDE82013426C001B8F2D /* SDWebImageIndicator.m in Sources */ = {isa = PBXBuildFile; fileRef = 32C0FDE02013426C001B8F2D /* SDWebImageIndicator.m */; };
32C0FDE92013426C001B8F2D /* SDWebImageIndicator.m in Sources */ = {isa = PBXBuildFile; fileRef = 32C0FDE02013426C001B8F2D /* SDWebImageIndicator.m */; };
32C0FDEA2013426C001B8F2D /* SDWebImageIndicator.m in Sources */ = {isa = PBXBuildFile; fileRef = 32C0FDE02013426C001B8F2D /* SDWebImageIndicator.m */; };
32C0FDEB2013426C001B8F2D /* SDWebImageIndicator.m in Sources */ = {isa = PBXBuildFile; fileRef = 32C0FDE02013426C001B8F2D /* SDWebImageIndicator.m */; };
32C0FDEC2013426C001B8F2D /* SDWebImageIndicator.m in Sources */ = {isa = PBXBuildFile; fileRef = 32C0FDE02013426C001B8F2D /* SDWebImageIndicator.m */; };
32CF1C071FA496B000004BD1 /* SDWebImageCoderHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 32CF1C051FA496B000004BD1 /* SDWebImageCoderHelper.h */; settings = {ATTRIBUTES = (Public, ); }; };
32CF1C081FA496B000004BD1 /* SDWebImageCoderHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 32CF1C051FA496B000004BD1 /* SDWebImageCoderHelper.h */; settings = {ATTRIBUTES = (Public, ); }; };
32CF1C091FA496B000004BD1 /* SDWebImageCoderHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 32CF1C051FA496B000004BD1 /* SDWebImageCoderHelper.h */; settings = {ATTRIBUTES = (Public, ); }; };
@ -1371,6 +1383,8 @@
3290FA031FA478AF0047D20C /* SDWebImageFrame.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDWebImageFrame.m; sourceTree = "<group>"; };
329A18571FFF5DFD008C9A2F /* UIImage+WebCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UIImage+WebCache.h"; path = "SDWebImage/UIImage+WebCache.h"; sourceTree = "<group>"; };
329A18581FFF5DFD008C9A2F /* UIImage+WebCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "UIImage+WebCache.m"; path = "SDWebImage/UIImage+WebCache.m"; sourceTree = "<group>"; };
32C0FDDF2013426C001B8F2D /* SDWebImageIndicator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDWebImageIndicator.h; sourceTree = "<group>"; };
32C0FDE02013426C001B8F2D /* SDWebImageIndicator.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDWebImageIndicator.m; sourceTree = "<group>"; };
32CF1C051FA496B000004BD1 /* SDWebImageCoderHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDWebImageCoderHelper.h; sourceTree = "<group>"; };
32CF1C061FA496B000004BD1 /* SDWebImageCoderHelper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDWebImageCoderHelper.m; sourceTree = "<group>"; };
4314D1991D0E0E3B004B36C9 /* libSDWebImage watchOS static.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libSDWebImage watchOS static.a"; sourceTree = BUILT_PRODUCTS_DIR; };
@ -1856,6 +1870,8 @@
324DF4B3200A14DC008A84CC /* SDWebImageDefine.m */,
325312C6200F09910046BF1E /* SDWebImageTransition.h */,
325312C7200F09910046BF1E /* SDWebImageTransition.m */,
32C0FDDF2013426C001B8F2D /* SDWebImageIndicator.h */,
32C0FDE02013426C001B8F2D /* SDWebImageIndicator.m */,
);
name = Utils;
sourceTree = "<group>";
@ -2105,6 +2121,7 @@
323F8BF91F38EF770092B609 /* animi.h in Headers */,
80377C4F1F2F666300F89830 /* filters_utils.h in Headers */,
80377C4C1F2F666300F89830 /* color_cache_utils.h in Headers */,
32C0FDE42013426C001B8F2D /* SDWebImageIndicator.h in Headers */,
321E60C11F38E91700405457 /* UIImage+ForceDecode.h in Headers */,
80377DBE1F2F66A700F89830 /* dsp.h in Headers */,
80377EB81F2F66D400F89830 /* alphai_dec.h in Headers */,
@ -2163,6 +2180,7 @@
80377C1B1F2F666300F89830 /* filters_utils.h in Headers */,
323F8B6F1F38EF770092B609 /* delta_palettization_enc.h in Headers */,
4314D1781D0E0E3B004B36C9 /* SDWebImageDownloader.h in Headers */,
32C0FDE22013426C001B8F2D /* SDWebImageIndicator.h in Headers */,
80377E981F2F66D400F89830 /* alphai_dec.h in Headers */,
4314D1791D0E0E3B004B36C9 /* SDWebImageManager.h in Headers */,
323F8BE51F38EF770092B609 /* vp8li_enc.h in Headers */,
@ -2243,6 +2261,7 @@
80377C671F2F666400F89830 /* endian_inl_utils.h in Headers */,
80377C6B1F2F666400F89830 /* huffman_encode_utils.h in Headers */,
323F8C121F38EF770092B609 /* muxi.h in Headers */,
32C0FDE52013426C001B8F2D /* SDWebImageIndicator.h in Headers */,
80377ED61F2F66D500F89830 /* webpi_dec.h in Headers */,
323F8BE81F38EF770092B609 /* vp8li_enc.h in Headers */,
323F8B8A1F38EF770092B609 /* histogram_enc.h in Headers */,
@ -2326,6 +2345,7 @@
80377E3A1F2F66A800F89830 /* common_sse2.h in Headers */,
4397D2D91D0DDD8C00BB2784 /* SDWebImagePrefetcher.h in Headers */,
80377C871F2F666400F89830 /* huffman_utils.h in Headers */,
32C0FDE62013426C001B8F2D /* SDWebImageIndicator.h in Headers */,
4397D2DA1D0DDD8C00BB2784 /* UIView+WebCacheOperation.h in Headers */,
80377E661F2F66A800F89830 /* neon.h in Headers */,
4397D2DB1D0DDD8C00BB2784 /* UIImage+MultiFormat.h in Headers */,
@ -2427,6 +2447,7 @@
80377C351F2F666300F89830 /* filters_utils.h in Headers */,
80377C321F2F666300F89830 /* color_cache_utils.h in Headers */,
321E60C01F38E91700405457 /* UIImage+ForceDecode.h in Headers */,
32C0FDE32013426C001B8F2D /* SDWebImageIndicator.h in Headers */,
80377D791F2F66A700F89830 /* dsp.h in Headers */,
80377EA81F2F66D400F89830 /* alphai_dec.h in Headers */,
4A2CAE2D1AB4BB7500B6BC39 /* UIImage+GIF.h in Headers */,
@ -2449,6 +2470,7 @@
53761316155AD0D5005750A4 /* SDImageCache.h in Headers */,
323F8C0E1F38EF770092B609 /* muxi.h in Headers */,
325312C8200F09910046BF1E /* SDWebImageTransition.h in Headers */,
32C0FDE12013426C001B8F2D /* SDWebImageIndicator.h in Headers */,
321E60A21F38E8F600405457 /* SDWebImageGIFCoder.h in Headers */,
5D5B9142188EE8DD006D06BD /* NSData+ImageContentType.h in Headers */,
80377BFE1F2F665300F89830 /* color_cache_utils.h in Headers */,
@ -2779,6 +2801,7 @@
321E60B91F38E90100405457 /* SDWebImageWebPCoder.m in Sources */,
80377DEB1F2F66A700F89830 /* yuv.c in Sources */,
3237F9E920161AE000A88143 /* NSImage+Additions.m in Sources */,
32C0FDEA2013426C001B8F2D /* SDWebImageIndicator.m in Sources */,
00733A551BC4880000A5A117 /* SDWebImageDownloader.m in Sources */,
80377EB71F2F66D400F89830 /* alpha_dec.c in Sources */,
80377DC61F2F66A700F89830 /* enc.c in Sources */,
@ -2980,6 +3003,7 @@
323F8BA91F38EF770092B609 /* picture_psnr_enc.c in Sources */,
323F8C091F38EF770092B609 /* muxedit.c in Sources */,
80377D1F1F2F66A700F89830 /* alpha_processing_neon.c in Sources */,
32C0FDE82013426C001B8F2D /* SDWebImageIndicator.m in Sources */,
4314D1401D0E0E3B004B36C9 /* UIImageView+WebCache.m in Sources */,
43A9186C1D8308FE00B3925F /* SDImageCacheConfig.m in Sources */,
3237F9EC20161AE000A88143 /* NSImage+Additions.m in Sources */,
@ -3127,6 +3151,7 @@
80377C611F2F666400F89830 /* bit_reader_utils.c in Sources */,
323F8BAC1F38EF770092B609 /* picture_psnr_enc.c in Sources */,
323F8C0C1F38EF770092B609 /* muxedit.c in Sources */,
32C0FDEB2013426C001B8F2D /* SDWebImageIndicator.m in Sources */,
80377DEE1F2F66A800F89830 /* alpha_processing_neon.c in Sources */,
43C892A41D9D6DDD0022038D /* demux.c in Sources */,
3237F9EA20161AE000A88143 /* NSImage+Additions.m in Sources */,
@ -3312,6 +3337,7 @@
4369C2831D9807EC007E863A /* UIView+WebCache.m in Sources */,
80377E611F2F66A800F89830 /* lossless_sse2.c in Sources */,
80377E691F2F66A800F89830 /* rescaler_msa.c in Sources */,
32C0FDEC2013426C001B8F2D /* SDWebImageIndicator.m in Sources */,
80377E5E1F2F66A800F89830 /* lossless_mips_dsp_r2.c in Sources */,
80377E3D1F2F66A800F89830 /* cost_sse2.c in Sources */,
321E60BB1F38E90100405457 /* SDWebImageWebPCoder.m in Sources */,
@ -3373,6 +3399,7 @@
321E60B81F38E90100405457 /* SDWebImageWebPCoder.m in Sources */,
43CE757A1CFE9427006C64D0 /* FLAnimatedImage.m in Sources */,
3237F9E820161AE000A88143 /* NSImage+Additions.m in Sources */,
32C0FDE92013426C001B8F2D /* SDWebImageIndicator.m in Sources */,
80377D811F2F66A700F89830 /* enc.c in Sources */,
80377EA71F2F66D400F89830 /* alpha_dec.c in Sources */,
80377D8F1F2F66A700F89830 /* lossless_mips_dsp_r2.c in Sources */,
@ -3524,6 +3551,7 @@
43CE75791CFE9427006C64D0 /* FLAnimatedImage.m in Sources */,
80377CF71F2F66A100F89830 /* enc.c in Sources */,
3237F9EB20161AE000A88143 /* NSImage+Additions.m in Sources */,
32C0FDE72013426C001B8F2D /* SDWebImageIndicator.m in Sources */,
80377E871F2F66D000F89830 /* alpha_dec.c in Sources */,
80377D051F2F66A100F89830 /* lossless_mips_dsp_r2.c in Sources */,
80377C0A1F2F665300F89830 /* random_utils.c in Sources */,

View File

@ -0,0 +1,107 @@
/*
* This file is part of the SDWebImage package.
* (c) Olivier Poitrey <rs@dailymotion.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
#import "SDWebImageCompat.h"
#if SD_UIKIT || SD_MAC
// A protocol to custom the indicator during the image loading
// All of these methods are called from main queue
@protocol SDWebImageIndicator <NSObject>
@required
/**
The view associate to the indicator.
@return The indicator view
*/
- (nonnull UIView *)indicatorView;
/**
Start the animating for indicator.
*/
- (void)startAnimatingIndicator;
/**
Stop the animating for indicator.
*/
- (void)stopAnimatingIndicator;
@end
// A protocol to custom the indicator which need update when loading progress changed
// All of these methods are called from main queue
@protocol SDWebImageProgressIndicator <SDWebImageIndicator>
@required
/**
Update the progress (0-1.0) for progress indicator.
@param progress The progress, value between 0 and 1.0
*/
- (void)updateProgress:(double)progress;
@end
#pragma mark - Activity Indicator
// Activity indicator class
// for UIKit(macOS), it use a `UIActivityIndicatorView`
// for AppKit(macOS), it use a `NSProgressIndicator` with the spinning style
@interface SDWebImageActivityIndicator : NSObject <SDWebImageIndicator>
#if SD_UIKIT
@property (nonatomic, strong, readonly, nonnull) UIActivityIndicatorView *indicatorView;
#else
@property (nonatomic, strong, readonly, nonnull) NSProgressIndicator *indicatorView;
#endif
@end
// Convenience way to use activity indicator.
@interface SDWebImageActivityIndicator (Conveniences)
/// gray-style activity indicator
@property (nonatomic, class, nonnull, readonly) SDWebImageActivityIndicator *grayIndicator __TVOS_UNAVAILABLE;
/// large gray-style activity indicator
@property (nonatomic, class, nonnull, readonly) SDWebImageActivityIndicator *grayLargeIndicator NS_AVAILABLE_MAC(10_2);
/// white-style activity indicator
@property (nonatomic, class, nonnull, readonly) SDWebImageActivityIndicator *whiteIndicator;
/// large white-style activity indicator
@property (nonatomic, class, nonnull, readonly) SDWebImageActivityIndicator *whiteLargeIndicator;
@end
#pragma mark - Progress Indicator
// Progress indicator class
// for UIKit(macOS), it use a `UIProgressView`
// for AppKit(macOS), it use a `NSProgressIndicator` with the bar style
@interface SDWebImageProgressIndicator : NSObject <SDWebImageProgressIndicator>
#if SD_UIKIT
@property (nonatomic, strong, readonly, nonnull) UIProgressView *indicatorView;
#else
@property (nonatomic, strong, readonly, nonnull) NSProgressIndicator *indicatorView;
#endif
/**
The preferred width for progress indicator. The getter and setter just pass to the indicatorView's frame. The default value is `UIProgressView`'s natural width.
*/
@property (nonatomic, assign) CGFloat indicatorWidth;
@end
// Convenience way to use progress indicator. Remember to set the indicatorWidth
@interface SDWebImageProgressIndicator (Conveniences)
/// default-style progress indicator
@property (nonatomic, class, nonnull, readonly) SDWebImageProgressIndicator *defaultIndicator;
/// bar-style progress indicator
@property (nonatomic, class, nonnull, readonly) SDWebImageProgressIndicator *barIndicator NS_AVAILABLE_IOS(2_0) __TVOS_UNAVAILABLE;
@end
#endif

View File

@ -0,0 +1,224 @@
/*
* This file is part of the SDWebImage package.
* (c) Olivier Poitrey <rs@dailymotion.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
#import "SDWebImageIndicator.h"
#if SD_UIKIT || SD_MAC
#if SD_MAC
#import <QuartzCore/QuartzCore.h>
#endif
#pragma mark - Activity Indicator
@interface SDWebImageActivityIndicator ()
#if SD_UIKIT
@property (nonatomic, strong, readwrite, nonnull) UIActivityIndicatorView *indicatorView;
#else
@property (nonatomic, strong, readwrite, nonnull) NSProgressIndicator *indicatorView;
#endif
@end
@implementation SDWebImageActivityIndicator
- (instancetype)init {
self = [super init];
if (self) {
[self commonInit];
}
return self;
}
#if SD_UIKIT
- (void)commonInit {
#if SD_TV
UIActivityIndicatorViewStyle style = UIActivityIndicatorViewStyleWhite;
#else
UIActivityIndicatorViewStyle style = UIActivityIndicatorViewStyleGray;
#endif
self.indicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:style];
self.indicatorView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin;
}
#endif
#if SD_MAC
- (void)commonInit {
self.indicatorView = [[NSProgressIndicator alloc] initWithFrame:NSZeroRect];
self.indicatorView.style = NSProgressIndicatorStyleSpinning;
self.indicatorView.controlSize = NSControlSizeSmall;
[self.indicatorView sizeToFit];
self.indicatorView.autoresizingMask = NSViewMaxXMargin | NSViewMinXMargin | NSViewMaxYMargin | NSViewMinYMargin;
}
#endif
- (void)startAnimatingIndicator {
#if SD_UIKIT
[self.indicatorView startAnimating];
#else
[self.indicatorView startAnimation:nil];
#endif
self.indicatorView.hidden = NO;
}
- (void)stopAnimatingIndicator {
#if SD_UIKIT
[self.indicatorView stopAnimating];
#else
[self.indicatorView stopAnimation:nil];
#endif
self.indicatorView.hidden = YES;
}
@end
@implementation SDWebImageActivityIndicator (Conveniences)
#if SD_MAC || SD_IOS
+ (SDWebImageActivityIndicator *)grayIndicator {
SDWebImageActivityIndicator *indicator = [SDWebImageActivityIndicator new];
return indicator;
}
#endif
#if SD_MAC
+ (SDWebImageActivityIndicator *)grayLargeIndicator {
SDWebImageActivityIndicator *indicator = SDWebImageActivityIndicator.grayIndicator;
indicator.indicatorView.controlSize = NSControlSizeRegular;
[indicator.indicatorView sizeToFit];
return indicator;
}
#endif
+ (SDWebImageActivityIndicator *)whiteIndicator {
SDWebImageActivityIndicator *indicator = [SDWebImageActivityIndicator new];
#if SD_UIKIT
indicator.indicatorView.activityIndicatorViewStyle = UIActivityIndicatorViewStyleWhite;
#else
CIFilter *lighten = [CIFilter filterWithName:@"CIColorControls"];
[lighten setDefaults];
[lighten setValue:@(1) forKey:kCIInputBrightnessKey];
indicator.indicatorView.contentFilters = @[lighten];
#endif
return indicator;
}
+ (SDWebImageActivityIndicator *)whiteLargeIndicator {
SDWebImageActivityIndicator *indicator = SDWebImageActivityIndicator.whiteIndicator;
#if SD_UIKIT
indicator.indicatorView.activityIndicatorViewStyle = UIActivityIndicatorViewStyleWhiteLarge;
#else
indicator.indicatorView.controlSize = NSControlSizeRegular;
[indicator.indicatorView sizeToFit];
#endif
return indicator;
}
@end
#pragma mark - Progress Indicator
@interface SDWebImageProgressIndicator ()
#if SD_UIKIT
@property (nonatomic, strong, readwrite, nonnull) UIProgressView *indicatorView;
#else
@property (nonatomic, strong, readwrite, nonnull) NSProgressIndicator *indicatorView;
#endif
@end
@implementation SDWebImageProgressIndicator
- (instancetype)init {
self = [super init];
if (self) {
[self commonInit];
}
return self;
}
#if SD_UIKIT
- (void)commonInit {
self.indicatorView = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleDefault];
self.indicatorView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin;
}
#endif
#if SD_MAC
- (void)commonInit {
self.indicatorView = [[NSProgressIndicator alloc] initWithFrame:NSMakeRect(0, 0, 160, 0)];
self.indicatorView.style = NSProgressIndicatorStyleBar;
self.indicatorView.controlSize = NSControlSizeSmall;
[self.indicatorView sizeToFit];
self.indicatorView.autoresizingMask = NSViewMaxXMargin | NSViewMinXMargin | NSViewMaxYMargin | NSViewMinYMargin;
}
#endif
- (CGFloat)indicatorWidth {
return self.indicatorView.frame.size.width;
}
- (void)setIndicatorWidth:(CGFloat)indicatorWidth {
CGRect frame = self.indicatorView.frame;
frame.size.width = indicatorWidth;
self.indicatorView.frame = frame;
}
- (void)startAnimatingIndicator {
self.indicatorView.hidden = NO;
#if SD_UIKIT
self.indicatorView.progress = 0;
#else
self.indicatorView.indeterminate = YES;
self.indicatorView.doubleValue = 0;
[self.indicatorView startAnimation:nil];
#endif
}
- (void)stopAnimatingIndicator {
self.indicatorView.hidden = YES;
#if SD_UIKIT
self.indicatorView.progress = 1;
#else
self.indicatorView.indeterminate = NO;
self.indicatorView.doubleValue = 1;
[self.indicatorView stopAnimation:nil];
#endif
}
- (void)updateProgress:(double)progress {
#if SD_UIKIT
[self.indicatorView setProgress:progress animated:YES];
#else
self.indicatorView.indeterminate = progress > 0 ? NO : YES;
self.indicatorView.doubleValue = progress * 100;
#endif
}
@end
@implementation SDWebImageProgressIndicator (Conveniences)
+ (SDWebImageProgressIndicator *)defaultIndicator {
SDWebImageProgressIndicator *indicator = [SDWebImageProgressIndicator new];
return indicator;
}
#if SD_IOS
+ (SDWebImageProgressIndicator *)barIndicator {
SDWebImageProgressIndicator *indicator = [SDWebImageProgressIndicator new];
indicator.indicatorView.progressViewStyle = UIProgressViewStyleBar;
return indicator;
}
#endif
@end
#endif

View File

@ -13,6 +13,7 @@
#import "SDWebImageDefine.h"
#import "SDWebImageManager.h"
#import "SDWebImageTransition.h"
#import "SDWebImageIndicator.h"
/**
The value specify that the image progress unit count cannot be determined because the progressBlock is not been called.
@ -106,27 +107,14 @@ typedef void(^SDSetImageBlock)(UIImage * _Nullable image, NSData * _Nullable ima
*/
@property (nonatomic, strong, nullable) SDWebImageTransition *sd_imageTransition;
#if SD_UIKIT
#pragma mark - Activity indicator
#pragma mark - Image Indicator
/**
* Show activity UIActivityIndicatorView
The image indicator during the image loading. If you do not need indicator, specify nil. Defaults to nil
The setter will remove the old indicator view and add new indicator view to current view's subview.
@note Because this is UI related, you should access only from the main queue.
*/
- (void)sd_setShowActivityIndicatorView:(BOOL)show;
/**
* set desired UIActivityIndicatorViewStyle
*
* @param style The style of the UIActivityIndicatorView
*/
- (void)sd_setIndicatorStyle:(UIActivityIndicatorViewStyle)style;
- (BOOL)sd_showActivityIndicatorView;
- (void)sd_addActivityIndicator;
- (void)sd_removeActivityIndicator;
#endif
@property (nonatomic, strong, nullable) id<SDWebImageIndicator> sd_imageIndicator;
@end

View File

@ -17,12 +17,6 @@ const int64_t SDWebImageProgressUnitCountUnknown = 1LL;
static char imageURLKey;
#if SD_UIKIT
static char TAG_ACTIVITY_INDICATOR;
static char TAG_ACTIVITY_STYLE;
#endif
static char TAG_ACTIVITY_SHOW;
@implementation UIView (WebCache)
- (nullable NSURL *)sd_imageURL {
@ -79,10 +73,8 @@ static char TAG_ACTIVITY_SHOW;
}
if (url) {
// check if activityView is enabled or not
if ([self sd_showActivityIndicatorView]) {
[self sd_addActivityIndicator];
}
// check and start image indicator
[self sd_startImageIndicator];
// reset the progress
self.sd_imageProgress.totalUnitCount = 0;
@ -95,6 +87,8 @@ static char TAG_ACTIVITY_SHOW;
manager = [SDWebImageManager sharedManager];
}
id<SDWebImageIndicator> imageIndicator = self.sd_imageIndicator;
__weak __typeof(self)wself = self;
SDWebImageDownloaderProgressBlock combinedProgressBlock = ^(NSInteger receivedSize, NSInteger expectedSize, NSURL * _Nullable targetURL) {
wself.sd_imageProgress.totalUnitCount = expectedSize;
@ -102,11 +96,20 @@ static char TAG_ACTIVITY_SHOW;
if (progressBlock) {
progressBlock(receivedSize, expectedSize, targetURL);
}
if ([imageIndicator conformsToProtocol:@protocol(SDWebImageProgressIndicator)]) {
double progress = wself.sd_imageProgress.fractionCompleted;
dispatch_async(dispatch_get_main_queue(), ^{
[((id<SDWebImageProgressIndicator>)imageIndicator) updateProgress:progress];
});
}
};
id <SDWebImageOperation> operation = [manager loadImageWithURL:url options:options progress:combinedProgressBlock completed:^(UIImage *image, NSData *data, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
__strong __typeof (wself) sself = wself;
if (!sself) { return; }
[sself sd_removeActivityIndicator];
// check and stop image indicator
if (finished) {
[self sd_stopImageIndicator];
}
// if the progress not been updated, mark it to complete state
if (finished && !error && sself.sd_imageProgress.totalUnitCount == 0 && sself.sd_imageProgress.completedUnitCount == 0) {
sself.sd_imageProgress.totalUnitCount = SDWebImageProgressUnitCountUnknown;
@ -170,8 +173,8 @@ static char TAG_ACTIVITY_SHOW;
} context:context];
[self sd_setImageLoadOperation:operation forKey:validOperationKey];
} else {
[self sd_stopImageIndicator];
dispatch_main_async_safe(^{
[self sd_removeActivityIndicator];
if (completedBlock) {
NSError *error = [NSError errorWithDomain:SDWebImageErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey : @"Trying to load a nil url"}];
completedBlock(nil, error, SDImageCacheTypeNone, url);
@ -277,75 +280,54 @@ static char TAG_ACTIVITY_SHOW;
objc_setAssociatedObject(self, @selector(sd_imageTransition), sd_imageTransition, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
#pragma mark - Activity indicator
#pragma mark -
#if SD_UIKIT
- (UIActivityIndicatorView *)activityIndicator {
return (UIActivityIndicatorView *)objc_getAssociatedObject(self, &TAG_ACTIVITY_INDICATOR);
#pragma mark - Indicator
- (id<SDWebImageIndicator>)sd_imageIndicator {
return objc_getAssociatedObject(self, @selector(sd_imageIndicator));
}
- (void)setActivityIndicator:(UIActivityIndicatorView *)activityIndicator {
objc_setAssociatedObject(self, &TAG_ACTIVITY_INDICATOR, activityIndicator, OBJC_ASSOCIATION_RETAIN);
}
- (void)setSd_imageIndicator:(id<SDWebImageIndicator>)sd_imageIndicator {
id<SDWebImageIndicator> previousIndicator = self.sd_imageIndicator;
if (previousIndicator == sd_imageIndicator) {
[previousIndicator.indicatorView removeFromSuperview];
}
// Add the new indicator view
UIView *view = sd_imageIndicator.indicatorView;
if (CGRectEqualToRect(view.frame, CGRectZero)) {
view.frame = self.frame;
}
// Center the indicator view
#if SD_MAC
CGPoint center = CGPointMake(NSMidX(self.bounds), NSMidY(self.bounds));
NSRect frame = view.frame;
view.frame = NSMakeRect(center.x - NSMidX(frame), center.y - NSMidY(frame), NSWidth(frame), NSHeight(frame));
#else
view.center = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
#endif
- (void)sd_setShowActivityIndicatorView:(BOOL)show {
objc_setAssociatedObject(self, &TAG_ACTIVITY_SHOW, @(show), OBJC_ASSOCIATION_RETAIN);
view.hidden = NO;
[self addSubview:view];
objc_setAssociatedObject(self, @selector(sd_imageIndicator), sd_imageIndicator, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (BOOL)sd_showActivityIndicatorView {
return [objc_getAssociatedObject(self, &TAG_ACTIVITY_SHOW) boolValue];
}
#if SD_UIKIT
- (void)sd_setIndicatorStyle:(UIActivityIndicatorViewStyle)style{
objc_setAssociatedObject(self, &TAG_ACTIVITY_STYLE, [NSNumber numberWithInt:style], OBJC_ASSOCIATION_RETAIN);
}
- (int)sd_getIndicatorStyle{
return [objc_getAssociatedObject(self, &TAG_ACTIVITY_STYLE) intValue];
}
#endif
- (void)sd_addActivityIndicator {
#if SD_UIKIT
- (void)sd_startImageIndicator {
id<SDWebImageIndicator> imageIndicator = self.sd_imageIndicator;
if (!imageIndicator) {
return;
}
dispatch_main_async_safe(^{
if (!self.activityIndicator) {
self.activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:[self sd_getIndicatorStyle]];
self.activityIndicator.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:self.activityIndicator];
[self addConstraint:[NSLayoutConstraint constraintWithItem:self.activityIndicator
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeCenterX
multiplier:1.0
constant:0.0]];
[self addConstraint:[NSLayoutConstraint constraintWithItem:self.activityIndicator
attribute:NSLayoutAttributeCenterY
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeCenterY
multiplier:1.0
constant:0.0]];
}
[self.activityIndicator startAnimating];
[imageIndicator startAnimatingIndicator];
});
#endif
}
- (void)sd_removeActivityIndicator {
#if SD_UIKIT
- (void)sd_stopImageIndicator {
id<SDWebImageIndicator> imageIndicator = self.sd_imageIndicator;
if (!imageIndicator) {
return;
}
dispatch_main_async_safe(^{
if (self.activityIndicator) {
[self.activityIndicator removeFromSuperview];
self.activityIndicator = nil;
}
[imageIndicator stopAnimatingIndicator];
});
#endif
}
@end

View File

@ -36,6 +36,7 @@ FOUNDATION_EXPORT const unsigned char WebImageVersionString[];
#import <SDWebImage/SDWebImageOperation.h>
#import <SDWebImage/SDWebImageDownloader.h>
#import <SDWebImage/SDWebImageTransition.h>
#import <SDWebImage/SDWebImageIndicator.h>
#if SD_MAC || SD_UIKIT
#import <SDWebImage/MKAnnotationView+WebCache.h>