Merge branch 'master' into xucg
This commit is contained in:
commit
23388717bc
44
CHANGELOG.md
44
CHANGELOG.md
|
@ -1,3 +1,45 @@
|
|||
## [4.4.1 - 4.4 patch, on June 7th, 2018](https://github.com/rs/SDWebImage/releases/tag/4.4.1)
|
||||
See [all tickets marked for the 4.4.1 release](https://github.com/rs/SDWebImage/milestone/26)
|
||||
|
||||
#### Fixes
|
||||
- Coder
|
||||
- Fix that WebP (including Animated WebP) decoding issue on iOS 12 #2348 #2347
|
||||
- Downloader
|
||||
- Fix that the downloader operation may not call the completion block when requesting the same image url in race condition #2346 #2344
|
||||
|
||||
## [4.4.0 - watchOS View Category, on May 31st, 2018](https://github.com/rs/SDWebImage/releases/tag/4.4.0)
|
||||
See [all tickets marked for the 4.4.0 release](https://github.com/rs/SDWebImage/milestone/25)
|
||||
|
||||
#### Features
|
||||
- View Category
|
||||
- Add the support for watchOS to use View Category method (`sd_setImageWithURL:`) on WKInterfaceImage #2343
|
||||
- Add optimalFrameCacheSize && predrawingEnabled options for FLAnimatedImage #2323
|
||||
- Cache
|
||||
- Add `SDImageCacheScaleDownLargeImages` to allow cache to scale down large images if need #2281 #2273
|
||||
|
||||
#### Improvements
|
||||
- View Category
|
||||
- Add `UIViewAnimationOptionAllowUserInteraction` as default options for convenient image transition #2315
|
||||
- Manager
|
||||
- Replace `@synchronized` with dispatch_semaphore_t in SDWebImageManager #2340
|
||||
|
||||
#### Performances
|
||||
- Coder
|
||||
- Remove the extra calculation of image orientation for ImageIO coder #2313
|
||||
- Remove the duplicated process to force decode (draw on bitmap context) in Image/IO's progressive decoding #2314
|
||||
- Common
|
||||
- Minor optimize for dispatch_queue_async_safe #2329
|
||||
|
||||
#### Fixes
|
||||
- Coder
|
||||
- Fix that force decode not works for alpha-channel images #2272 #2297
|
||||
- Fix WebP Encoding only works for RGBA8888 CGImage but not other color mode #2318
|
||||
- Fix the thread-safe issue for coders manager #2274 #2249 #1484
|
||||
- Fix the wrong declaration of NSArray generics #2260
|
||||
|
||||
#### Docs
|
||||
- Fix function storeImageDataToDisk description #2301
|
||||
|
||||
## [4.3.3 - Cache Serializer, on Mar 12th, 2018](https://github.com/rs/SDWebImage/releases/tag/4.3.3)
|
||||
See [all tickets marked for the 4.3.3 release](https://github.com/rs/SDWebImage/milestone/24)
|
||||
|
||||
|
@ -631,3 +673,5 @@ For consistency, added async methods in `SDWebImageManager` `cachedImageExistsFo
|
|||
## [1.0.0 on Dec 31st, 2009](https://github.com/rs/SDWebImage/releases/tag/1.0.0)
|
||||
|
||||
## [1.0 on Dec 31st, 2009](https://github.com/rs/SDWebImage/releases/tag/1.0)
|
||||
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
#import "InterfaceController.h"
|
||||
#import <SDWebImage/SDWebImageManager.h>
|
||||
#import <SDWebImage/UIImageView+WebCache.h>
|
||||
|
||||
|
||||
@interface InterfaceController()
|
||||
|
@ -30,9 +30,8 @@
|
|||
[super willActivate];
|
||||
|
||||
NSString *urlString = @"https://nr-platform.s3.amazonaws.com/uploads/platform/published_extension/branding_icon/275/AmazonS3.png";
|
||||
[[SDWebImageManager sharedManager] loadImageWithURL:[NSURL URLWithString:urlString] options:0 progress:nil completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL) {
|
||||
self.imageInterface.image = image;
|
||||
}];
|
||||
WKInterfaceImage *imageInterface = self.imageInterface;
|
||||
[imageInterface sd_setImageWithURL:[NSURL URLWithString:urlString]];
|
||||
}
|
||||
|
||||
- (void)didDeactivate {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
Pod::Spec.new do |s|
|
||||
s.name = 'SDWebImage'
|
||||
s.version = '4.3.3'
|
||||
s.version = '4.4.1'
|
||||
|
||||
s.osx.deployment_target = '10.9'
|
||||
s.ios.deployment_target = '7.0'
|
||||
|
|
|
@ -38,6 +38,20 @@
|
|||
*/
|
||||
@interface FLAnimatedImageView (WebCache)
|
||||
|
||||
/**
|
||||
* Optimal frame cache size of FLAnimatedImage during initializer. (1.0.11 version later)
|
||||
* This value will help you set `optimalFrameCacheSize` arg of FLAnimatedImage initializer after image load.
|
||||
* Defaults to 0.
|
||||
*/
|
||||
@property (nonatomic, assign) NSUInteger sd_optimalFrameCacheSize;
|
||||
|
||||
/**
|
||||
* Predrawing control of FLAnimatedImage during initializer. (1.0.11 version later)
|
||||
* This value will help you set `predrawingEnabled` arg of FLAnimatedImage initializer after image load.
|
||||
* Defaults to YES.
|
||||
*/
|
||||
@property (nonatomic, assign) BOOL sd_predrawingEnabled;
|
||||
|
||||
/**
|
||||
* Load the image at the given url (either from cache or download) and load it in this imageView. It works with both static and dynamic images
|
||||
* The download is asynchronous and cached.
|
||||
|
|
|
@ -29,6 +29,33 @@
|
|||
|
||||
@implementation FLAnimatedImageView (WebCache)
|
||||
|
||||
// These property based options will moved to `SDWebImageContext` in 5.x, to allow per-image-request level options instead of per-imageView-level options
|
||||
- (NSUInteger)sd_optimalFrameCacheSize {
|
||||
NSUInteger optimalFrameCacheSize = 0;
|
||||
NSNumber *value = objc_getAssociatedObject(self, @selector(sd_optimalFrameCacheSize));
|
||||
if ([value isKindOfClass:[NSNumber class]]) {
|
||||
optimalFrameCacheSize = value.unsignedShortValue;
|
||||
}
|
||||
return optimalFrameCacheSize;
|
||||
}
|
||||
|
||||
- (void)setSd_optimalFrameCacheSize:(NSUInteger)sd_optimalFrameCacheSize {
|
||||
objc_setAssociatedObject(self, @selector(sd_optimalFrameCacheSize), @(sd_optimalFrameCacheSize), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
}
|
||||
|
||||
- (BOOL)sd_predrawingEnabled {
|
||||
BOOL predrawingEnabled = YES;
|
||||
NSNumber *value = objc_getAssociatedObject(self, @selector(sd_predrawingEnabled));
|
||||
if ([value isKindOfClass:[NSNumber class]]) {
|
||||
predrawingEnabled = value.boolValue;
|
||||
}
|
||||
return predrawingEnabled;
|
||||
}
|
||||
|
||||
- (void)setSd_predrawingEnabled:(BOOL)sd_predrawingEnabled {
|
||||
objc_setAssociatedObject(self, @selector(sd_predrawingEnabled), @(sd_predrawingEnabled), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
}
|
||||
|
||||
- (void)sd_setImageWithURL:(nullable NSURL *)url {
|
||||
[self sd_setImageWithURL:url placeholderImage:nil options:0 progress:nil completed:nil];
|
||||
}
|
||||
|
@ -83,7 +110,13 @@
|
|||
weakSelf.animatedImage = nil;
|
||||
// Secondly create FLAnimatedImage in global queue because it's time consuming, then set it back
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
|
||||
FLAnimatedImage *animatedImage = [FLAnimatedImage animatedImageWithGIFData:imageData];
|
||||
FLAnimatedImage *animatedImage;
|
||||
// Compatibility in 4.x for lower version FLAnimatedImage.
|
||||
if ([FLAnimatedImage respondsToSelector:@selector(initWithAnimatedGIFData:optimalFrameCacheSize:predrawingEnabled:)]) {
|
||||
animatedImage = [[FLAnimatedImage alloc] initWithAnimatedGIFData:imageData optimalFrameCacheSize:self.sd_optimalFrameCacheSize predrawingEnabled:self.sd_predrawingEnabled];
|
||||
} else {
|
||||
animatedImage = [[FLAnimatedImage alloc] initWithAnimatedGIFData:imageData];
|
||||
}
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
image.sd_FLAnimatedImage = animatedImage;
|
||||
weakSelf.animatedImage = animatedImage;
|
||||
|
|
|
@ -606,7 +606,23 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
|
|||
- (void)deleteOldFilesWithCompletionBlock:(nullable SDWebImageNoParamsBlock)completionBlock {
|
||||
dispatch_async(self.ioQueue, ^{
|
||||
NSURL *diskCacheURL = [NSURL fileURLWithPath:self.diskCachePath isDirectory:YES];
|
||||
NSArray<NSString *> *resourceKeys = @[NSURLIsDirectoryKey, NSURLContentModificationDateKey, NSURLTotalFileAllocatedSizeKey];
|
||||
|
||||
// Compute content date key to be used for tests
|
||||
NSURLResourceKey cacheContentDateKey = NSURLContentModificationDateKey;
|
||||
switch (self.config.diskCacheExpireType) {
|
||||
case SDImageCacheConfigExpireTypeAccessDate:
|
||||
cacheContentDateKey = NSURLContentAccessDateKey;
|
||||
break;
|
||||
|
||||
case SDImageCacheConfigExpireTypeModificationDate:
|
||||
cacheContentDateKey = NSURLContentModificationDateKey;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
NSArray<NSString *> *resourceKeys = @[NSURLIsDirectoryKey, cacheContentDateKey, NSURLTotalFileAllocatedSizeKey];
|
||||
|
||||
// This enumerator prefetches useful properties for our cache files.
|
||||
NSDirectoryEnumerator *fileEnumerator = [self.fileManager enumeratorAtURL:diskCacheURL
|
||||
|
@ -633,12 +649,12 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
|
|||
}
|
||||
|
||||
// Remove files that are older than the expiration date;
|
||||
NSDate *modificationDate = resourceValues[NSURLContentModificationDateKey];
|
||||
if ([[modificationDate laterDate:expirationDate] isEqualToDate:expirationDate]) {
|
||||
NSDate *modifiedDate = resourceValues[cacheContentDateKey];
|
||||
if ([[modifiedDate laterDate:expirationDate] isEqualToDate:expirationDate]) {
|
||||
[urlsToDelete addObject:fileURL];
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// Store a reference to this file and account for its total size.
|
||||
NSNumber *totalAllocatedSize = resourceValues[NSURLTotalFileAllocatedSizeKey];
|
||||
currentCacheSize += totalAllocatedSize.unsignedIntegerValue;
|
||||
|
|
|
@ -9,6 +9,17 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
#import "SDWebImageCompat.h"
|
||||
|
||||
typedef NS_ENUM(NSUInteger, SDImageCacheConfigExpireType) {
|
||||
/**
|
||||
* When the image is accessed it will update this value
|
||||
*/
|
||||
SDImageCacheConfigExpireTypeAccessDate,
|
||||
/**
|
||||
* The image was obtained from the disk cache (Default)
|
||||
*/
|
||||
SDImageCacheConfigExpireTypeModificationDate
|
||||
};
|
||||
|
||||
@interface SDImageCacheConfig : NSObject
|
||||
|
||||
/**
|
||||
|
@ -49,4 +60,10 @@
|
|||
*/
|
||||
@property (assign, nonatomic) NSUInteger maxCacheSize;
|
||||
|
||||
/**
|
||||
* The attribute which the clear cache will be checked against when clearing the disk cache
|
||||
* Default is Modified Date
|
||||
*/
|
||||
@property (assign, nonatomic) SDImageCacheConfigExpireType diskCacheExpireType;
|
||||
|
||||
@end
|
||||
|
|
|
@ -21,6 +21,7 @@ static const NSInteger kDefaultCacheMaxCacheAge = 60 * 60 * 24 * 7; // 1 week
|
|||
_diskCacheWritingOptions = NSDataWritingAtomic;
|
||||
_maxCacheAge = kDefaultCacheMaxCacheAge;
|
||||
_maxCacheSize = 0;
|
||||
_diskCacheExpireType = SDImageCacheConfigExpireTypeModificationDate;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
|
|
@ -70,6 +70,12 @@
|
|||
#endif
|
||||
#if SD_WATCH
|
||||
#import <WatchKit/WatchKit.h>
|
||||
#ifndef UIView
|
||||
#define UIView WKInterfaceObject
|
||||
#endif
|
||||
#ifndef UIImageView
|
||||
#define UIImageView WKInterfaceImage
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -89,7 +95,7 @@ FOUNDATION_EXPORT NSString *const SDWebImageErrorDomain;
|
|||
|
||||
#ifndef dispatch_queue_async_safe
|
||||
#define dispatch_queue_async_safe(queue, block)\
|
||||
if (strcmp(dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL), dispatch_queue_get_label(queue)) == 0) {\
|
||||
if (dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL) == dispatch_queue_get_label(queue)) {\
|
||||
block();\
|
||||
} else {\
|
||||
dispatch_async(queue, block);\
|
||||
|
|
|
@ -251,7 +251,9 @@
|
|||
|
||||
LOCK(self.operationsLock);
|
||||
SDWebImageDownloaderOperation *operation = [self.URLOperations objectForKey:url];
|
||||
if (!operation) {
|
||||
|
||||
// There is a case that the operation may be marked as finished, but not been removed from `self.URLOperations`.
|
||||
if (!operation || operation.isFinished) {
|
||||
operation = [self createDownloaderOperationWithUrl:url options:options];
|
||||
__weak typeof(self) wself = self;
|
||||
operation.completionBlock = ^{
|
||||
|
|
|
@ -10,6 +10,9 @@
|
|||
#import "NSImage+WebCache.h"
|
||||
#import <objc/message.h>
|
||||
|
||||
#define LOCK(lock) dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER);
|
||||
#define UNLOCK(lock) dispatch_semaphore_signal(lock);
|
||||
|
||||
@interface SDWebImageCombinedOperation : NSObject <SDWebImageOperation>
|
||||
|
||||
@property (assign, nonatomic, getter = isCancelled) BOOL cancelled;
|
||||
|
@ -24,7 +27,9 @@
|
|||
@property (strong, nonatomic, readwrite, nonnull) SDImageCache *imageCache;
|
||||
@property (strong, nonatomic, readwrite, nonnull) SDWebImageDownloader *imageDownloader;
|
||||
@property (strong, nonatomic, nonnull) NSMutableSet<NSURL *> *failedURLs;
|
||||
@property (strong, nonatomic, nonnull) dispatch_semaphore_t failedURLsLock; // a lock to keep the access to `failedURLs` thread-safe
|
||||
@property (strong, nonatomic, nonnull) NSMutableArray<SDWebImageCombinedOperation *> *runningOperations;
|
||||
@property (strong, nonatomic, nonnull) dispatch_semaphore_t runningOperationsLock; // a lock to keep the access to `runningOperations` thread-safe
|
||||
|
||||
@end
|
||||
|
||||
|
@ -50,7 +55,9 @@
|
|||
_imageCache = cache;
|
||||
_imageDownloader = downloader;
|
||||
_failedURLs = [NSMutableSet new];
|
||||
_failedURLsLock = dispatch_semaphore_create(1);
|
||||
_runningOperations = [NSMutableArray new];
|
||||
_runningOperationsLock = dispatch_semaphore_create(1);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
@ -130,9 +137,9 @@
|
|||
|
||||
BOOL isFailedUrl = NO;
|
||||
if (url) {
|
||||
@synchronized (self.failedURLs) {
|
||||
isFailedUrl = [self.failedURLs containsObject:url];
|
||||
}
|
||||
LOCK(self.failedURLsLock);
|
||||
isFailedUrl = [self.failedURLs containsObject:url];
|
||||
UNLOCK(self.failedURLsLock);
|
||||
}
|
||||
|
||||
if (url.absoluteString.length == 0 || (!(options & SDWebImageRetryFailed) && isFailedUrl)) {
|
||||
|
@ -140,9 +147,9 @@
|
|||
return operation;
|
||||
}
|
||||
|
||||
@synchronized (self.runningOperations) {
|
||||
[self.runningOperations addObject:operation];
|
||||
}
|
||||
LOCK(self.runningOperationsLock);
|
||||
[self.runningOperations addObject:operation];
|
||||
UNLOCK(self.runningOperationsLock);
|
||||
NSString *key = [self cacheKeyForURL:url];
|
||||
|
||||
SDImageCacheOptions cacheOptions = 0;
|
||||
|
@ -213,16 +220,16 @@
|
|||
}
|
||||
|
||||
if (shouldBlockFailedURL) {
|
||||
@synchronized (self.failedURLs) {
|
||||
[self.failedURLs addObject:url];
|
||||
}
|
||||
LOCK(self.failedURLsLock);
|
||||
[self.failedURLs addObject:url];
|
||||
UNLOCK(self.failedURLsLock);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ((options & SDWebImageRetryFailed)) {
|
||||
@synchronized (self.failedURLs) {
|
||||
[self.failedURLs removeObject:url];
|
||||
}
|
||||
LOCK(self.failedURLsLock);
|
||||
[self.failedURLs removeObject:url];
|
||||
UNLOCK(self.failedURLsLock);
|
||||
}
|
||||
|
||||
BOOL cacheOnDisk = !(options & SDWebImageCacheMemoryOnly);
|
||||
|
@ -292,27 +299,27 @@
|
|||
}
|
||||
|
||||
- (void)cancelAll {
|
||||
@synchronized (self.runningOperations) {
|
||||
NSArray<SDWebImageCombinedOperation *> *copiedOperations = [self.runningOperations copy];
|
||||
[copiedOperations makeObjectsPerformSelector:@selector(cancel)];
|
||||
[self.runningOperations removeObjectsInArray:copiedOperations];
|
||||
}
|
||||
LOCK(self.runningOperationsLock);
|
||||
NSArray<SDWebImageCombinedOperation *> *copiedOperations = [self.runningOperations copy];
|
||||
UNLOCK(self.runningOperationsLock);
|
||||
[copiedOperations makeObjectsPerformSelector:@selector(cancel)]; // This will call `safelyRemoveOperationFromRunning:` and remove from the array
|
||||
}
|
||||
|
||||
- (BOOL)isRunning {
|
||||
BOOL isRunning = NO;
|
||||
@synchronized (self.runningOperations) {
|
||||
isRunning = (self.runningOperations.count > 0);
|
||||
}
|
||||
LOCK(self.runningOperationsLock);
|
||||
isRunning = (self.runningOperations.count > 0);
|
||||
UNLOCK(self.runningOperationsLock);
|
||||
return isRunning;
|
||||
}
|
||||
|
||||
- (void)safelyRemoveOperationFromRunning:(nullable SDWebImageCombinedOperation*)operation {
|
||||
@synchronized (self.runningOperations) {
|
||||
if (operation) {
|
||||
[self.runningOperations removeObject:operation];
|
||||
}
|
||||
if (!operation) {
|
||||
return;
|
||||
}
|
||||
LOCK(self.runningOperationsLock);
|
||||
[self.runningOperations removeObject:operation];
|
||||
UNLOCK(self.runningOperationsLock);
|
||||
}
|
||||
|
||||
- (void)callCompletionBlockForOperation:(nullable SDWebImageCombinedOperation*)operation
|
||||
|
|
|
@ -73,9 +73,12 @@
|
|||
int canvasWidth = WebPDemuxGetI(demuxer, WEBP_FF_CANVAS_WIDTH);
|
||||
int canvasHeight = WebPDemuxGetI(demuxer, WEBP_FF_CANVAS_HEIGHT);
|
||||
CGBitmapInfo bitmapInfo;
|
||||
// `CGBitmapContextCreate` does not support RGB888 on iOS. Where `CGImageCreate` supports.
|
||||
if (!(flags & ALPHA_FLAG)) {
|
||||
// RGBX8888
|
||||
bitmapInfo = kCGBitmapByteOrder32Big | kCGImageAlphaNoneSkipLast;
|
||||
} else {
|
||||
// RGBA8888
|
||||
bitmapInfo = kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast;
|
||||
}
|
||||
CGContextRef canvas = CGBitmapContextCreate(NULL, canvasWidth, canvasHeight, 8, 0, SDCGColorSpaceGetDeviceRGB(), bitmapInfo);
|
||||
|
@ -298,7 +301,15 @@
|
|||
CGDataProviderRef provider =
|
||||
CGDataProviderCreateWithData(NULL, config.output.u.RGBA.rgba, config.output.u.RGBA.size, FreeImageData);
|
||||
CGColorSpaceRef colorSpaceRef = SDCGColorSpaceGetDeviceRGB();
|
||||
CGBitmapInfo bitmapInfo = config.input.has_alpha ? kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast : kCGBitmapByteOrder32Big | kCGImageAlphaNoneSkipLast;
|
||||
CGBitmapInfo bitmapInfo;
|
||||
// `CGBitmapContextCreate` does not support RGB888 on iOS. Where `CGImageCreate` supports.
|
||||
if (!config.input.has_alpha) {
|
||||
// RGB888
|
||||
bitmapInfo = kCGBitmapByteOrder32Big | kCGImageAlphaNone;
|
||||
} else {
|
||||
// RGBA8888
|
||||
bitmapInfo = kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast;
|
||||
}
|
||||
size_t components = config.input.has_alpha ? 4 : 3;
|
||||
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
|
||||
CGImageRef imageRef = CGImageCreate(width, height, 8, components * 8, components * width, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);
|
||||
|
|
|
@ -7,9 +7,6 @@
|
|||
*/
|
||||
|
||||
#import "SDWebImageCompat.h"
|
||||
|
||||
#if SD_UIKIT || SD_MAC
|
||||
|
||||
#import "SDWebImageManager.h"
|
||||
|
||||
/**
|
||||
|
@ -195,5 +192,3 @@
|
|||
#endif
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
|
|
|
@ -7,9 +7,6 @@
|
|||
*/
|
||||
|
||||
#import "UIImageView+WebCache.h"
|
||||
|
||||
#if SD_UIKIT || SD_MAC
|
||||
|
||||
#import "objc/runtime.h"
|
||||
#import "UIView+WebCacheOperation.h"
|
||||
#import "UIView+WebCache.h"
|
||||
|
@ -140,5 +137,3 @@ static char animationLoadOperationKey;
|
|||
#endif
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
|
|
|
@ -7,9 +7,6 @@
|
|||
*/
|
||||
|
||||
#import "SDWebImageCompat.h"
|
||||
|
||||
#if SD_UIKIT || SD_MAC
|
||||
|
||||
#import "SDWebImageManager.h"
|
||||
#import "SDWebImageTransition.h"
|
||||
|
||||
|
@ -105,6 +102,8 @@ typedef void(^SDSetImageBlock)(UIImage * _Nullable image, NSData * _Nullable ima
|
|||
*/
|
||||
- (void)sd_cancelCurrentImageLoad;
|
||||
|
||||
#if SD_UIKIT || SD_MAC
|
||||
|
||||
#pragma mark - Image Transition
|
||||
|
||||
/**
|
||||
|
@ -135,6 +134,6 @@ typedef void(^SDSetImageBlock)(UIImage * _Nullable image, NSData * _Nullable ima
|
|||
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
|
|
@ -7,9 +7,6 @@
|
|||
*/
|
||||
|
||||
#import "UIView+WebCache.h"
|
||||
|
||||
#if SD_UIKIT || SD_MAC
|
||||
|
||||
#import "objc/runtime.h"
|
||||
#import "UIView+WebCacheOperation.h"
|
||||
|
||||
|
@ -23,8 +20,8 @@ static char imageURLKey;
|
|||
#if SD_UIKIT
|
||||
static char TAG_ACTIVITY_INDICATOR;
|
||||
static char TAG_ACTIVITY_STYLE;
|
||||
#endif
|
||||
static char TAG_ACTIVITY_SHOW;
|
||||
#endif
|
||||
|
||||
@implementation UIView (WebCache)
|
||||
|
||||
|
@ -78,10 +75,12 @@ static char TAG_ACTIVITY_SHOW;
|
|||
}
|
||||
|
||||
if (url) {
|
||||
#if SD_UIKIT
|
||||
// check if activityView is enabled or not
|
||||
if ([self sd_showActivityIndicatorView]) {
|
||||
[self sd_addActivityIndicator];
|
||||
}
|
||||
#endif
|
||||
|
||||
// reset the progress
|
||||
self.sd_imageProgress.totalUnitCount = 0;
|
||||
|
@ -105,7 +104,9 @@ static char TAG_ACTIVITY_SHOW;
|
|||
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; }
|
||||
#if SD_UIKIT
|
||||
[sself sd_removeActivityIndicator];
|
||||
#endif
|
||||
// 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;
|
||||
|
@ -144,16 +145,22 @@ static char TAG_ACTIVITY_SHOW;
|
|||
targetData = nil;
|
||||
}
|
||||
|
||||
#if SD_UIKIT || SD_MAC
|
||||
// check whether we should use the image transition
|
||||
SDWebImageTransition *transition = nil;
|
||||
if (finished && (options & SDWebImageForceTransition || cacheType == SDImageCacheTypeNone)) {
|
||||
transition = sself.sd_imageTransition;
|
||||
}
|
||||
#endif
|
||||
if ([context valueForKey:SDWebImageInternalSetImageGroupKey]) {
|
||||
dispatch_group_t group = [context valueForKey:SDWebImageInternalSetImageGroupKey];
|
||||
dispatch_group_enter(group);
|
||||
dispatch_main_async_safe(^{
|
||||
#if SD_UIKIT || SD_MAC
|
||||
[sself sd_setImage:targetImage imageData:targetData basedOnClassOrViaCustomSetImageBlock:setImageBlock transition:transition cacheType:cacheType imageURL:imageURL];
|
||||
#else
|
||||
[sself sd_setImage:targetImage imageData:targetData basedOnClassOrViaCustomSetImageBlock:setImageBlock];
|
||||
#endif
|
||||
});
|
||||
// ensure completion block is called after custom setImage process finish
|
||||
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
|
||||
|
@ -161,7 +168,11 @@ static char TAG_ACTIVITY_SHOW;
|
|||
});
|
||||
} else {
|
||||
dispatch_main_async_safe(^{
|
||||
#if SD_UIKIT || SD_MAC
|
||||
[sself sd_setImage:targetImage imageData:targetData basedOnClassOrViaCustomSetImageBlock:setImageBlock transition:transition cacheType:cacheType imageURL:imageURL];
|
||||
#else
|
||||
[sself sd_setImage:targetImage imageData:targetData basedOnClassOrViaCustomSetImageBlock:setImageBlock];
|
||||
#endif
|
||||
callCompletedBlockClojure();
|
||||
});
|
||||
}
|
||||
|
@ -169,7 +180,9 @@ static char TAG_ACTIVITY_SHOW;
|
|||
[self sd_setImageLoadOperation:operation forKey:validOperationKey];
|
||||
} else {
|
||||
dispatch_main_async_safe(^{
|
||||
#if SD_UIKIT
|
||||
[self sd_removeActivityIndicator];
|
||||
#endif
|
||||
if (completedBlock) {
|
||||
NSError *error = [NSError errorWithDomain:SDWebImageErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey : @"Trying to load a nil url"}];
|
||||
completedBlock(nil, error, SDImageCacheTypeNone, url);
|
||||
|
@ -183,23 +196,31 @@ static char TAG_ACTIVITY_SHOW;
|
|||
}
|
||||
|
||||
- (void)sd_setImage:(UIImage *)image imageData:(NSData *)imageData basedOnClassOrViaCustomSetImageBlock:(SDSetImageBlock)setImageBlock {
|
||||
#if SD_UIKIT || SD_MAC
|
||||
[self sd_setImage:image imageData:imageData basedOnClassOrViaCustomSetImageBlock:setImageBlock transition:nil cacheType:0 imageURL:nil];
|
||||
#else
|
||||
// watchOS does not support view transition. Simplify the logic
|
||||
if (setImageBlock) {
|
||||
setImageBlock(image, imageData);
|
||||
} else if ([self isKindOfClass:[UIImageView class]]) {
|
||||
UIImageView *imageView = (UIImageView *)self;
|
||||
[imageView setImage:image];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if SD_UIKIT || SD_MAC
|
||||
- (void)sd_setImage:(UIImage *)image imageData:(NSData *)imageData basedOnClassOrViaCustomSetImageBlock:(SDSetImageBlock)setImageBlock transition:(SDWebImageTransition *)transition cacheType:(SDImageCacheType)cacheType imageURL:(NSURL *)imageURL {
|
||||
UIView *view = self;
|
||||
SDSetImageBlock finalSetImageBlock;
|
||||
if (setImageBlock) {
|
||||
finalSetImageBlock = setImageBlock;
|
||||
}
|
||||
#if SD_UIKIT || SD_MAC
|
||||
else if ([view isKindOfClass:[UIImageView class]]) {
|
||||
} else if ([view isKindOfClass:[UIImageView class]]) {
|
||||
UIImageView *imageView = (UIImageView *)view;
|
||||
finalSetImageBlock = ^(UIImage *setImage, NSData *setImageData) {
|
||||
imageView.image = setImage;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
#if SD_UIKIT
|
||||
else if ([view isKindOfClass:[UIButton class]]) {
|
||||
UIButton *button = (UIButton *)view;
|
||||
|
@ -257,15 +278,20 @@ static char TAG_ACTIVITY_SHOW;
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
- (void)sd_setNeedsLayout {
|
||||
#if SD_UIKIT
|
||||
[self setNeedsLayout];
|
||||
#elif SD_MAC
|
||||
[self setNeedsLayout:YES];
|
||||
#elif SD_WATCH
|
||||
// Do nothing because WatchKit automatically layout the view after property change
|
||||
#endif
|
||||
}
|
||||
|
||||
#if SD_UIKIT || SD_MAC
|
||||
|
||||
#pragma mark - Image Transition
|
||||
- (SDWebImageTransition *)sd_imageTransition {
|
||||
return objc_getAssociatedObject(self, @selector(sd_imageTransition));
|
||||
|
@ -275,10 +301,9 @@ 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
|
||||
|
||||
#pragma mark - Activity indicator
|
||||
- (UIActivityIndicatorView *)activityIndicator {
|
||||
return (UIActivityIndicatorView *)objc_getAssociatedObject(self, &TAG_ACTIVITY_INDICATOR);
|
||||
}
|
||||
|
@ -286,7 +311,6 @@ static char TAG_ACTIVITY_SHOW;
|
|||
- (void)setActivityIndicator:(UIActivityIndicatorView *)activityIndicator {
|
||||
objc_setAssociatedObject(self, &TAG_ACTIVITY_INDICATOR, activityIndicator, OBJC_ASSOCIATION_RETAIN);
|
||||
}
|
||||
#endif
|
||||
|
||||
- (void)sd_setShowActivityIndicatorView:(BOOL)show {
|
||||
objc_setAssociatedObject(self, &TAG_ACTIVITY_SHOW, @(show), OBJC_ASSOCIATION_RETAIN);
|
||||
|
@ -296,7 +320,6 @@ static char TAG_ACTIVITY_SHOW;
|
|||
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);
|
||||
}
|
||||
|
@ -304,10 +327,8 @@ static char TAG_ACTIVITY_SHOW;
|
|||
- (int)sd_getIndicatorStyle{
|
||||
return [objc_getAssociatedObject(self, &TAG_ACTIVITY_STYLE) intValue];
|
||||
}
|
||||
#endif
|
||||
|
||||
- (void)sd_addActivityIndicator {
|
||||
#if SD_UIKIT
|
||||
dispatch_main_async_safe(^{
|
||||
if (!self.activityIndicator) {
|
||||
self.activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:[self sd_getIndicatorStyle]];
|
||||
|
@ -332,20 +353,19 @@ static char TAG_ACTIVITY_SHOW;
|
|||
}
|
||||
[self.activityIndicator startAnimating];
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)sd_removeActivityIndicator {
|
||||
#if SD_UIKIT
|
||||
dispatch_main_async_safe(^{
|
||||
if (self.activityIndicator) {
|
||||
[self.activityIndicator removeFromSuperview];
|
||||
self.activityIndicator = nil;
|
||||
}
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
@end
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
|
|
@ -7,10 +7,7 @@
|
|||
*/
|
||||
|
||||
#import "SDWebImageCompat.h"
|
||||
|
||||
#if SD_UIKIT || SD_MAC
|
||||
|
||||
#import "SDWebImageManager.h"
|
||||
#import "SDWebImageOperation.h"
|
||||
|
||||
// These methods are used to support canceling for UIView image loading, it's designed to be used internal but not external.
|
||||
// All the stored operations are weak, so it will be dalloced after image loading finished. If you need to store operations, use your own class to keep a strong reference for them.
|
||||
|
@ -39,5 +36,3 @@
|
|||
- (void)sd_removeImageLoadOperationWithKey:(nullable NSString *)key;
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
|
|
|
@ -7,9 +7,6 @@
|
|||
*/
|
||||
|
||||
#import "UIView+WebCacheOperation.h"
|
||||
|
||||
#if SD_UIKIT || SD_MAC
|
||||
|
||||
#import "objc/runtime.h"
|
||||
|
||||
static char loadOperationKey;
|
||||
|
@ -71,5 +68,3 @@ typedef NSMapTable<NSString *, id<SDWebImageOperation>> SDOperationsDictionary;
|
|||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
|
|
|
@ -15,11 +15,11 @@
|
|||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>4.3.3</string>
|
||||
<string>4.4.1</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>4.3.3</string>
|
||||
<string>4.4.1</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string></string>
|
||||
</dict>
|
||||
|
|
Loading…
Reference in New Issue