Merge branch 'master' into 5.x
This commit is contained in:
commit
ab06d2370b
25
CHANGELOG.md
25
CHANGELOG.md
|
@ -1,3 +1,28 @@
|
|||
## [4.2.0 - Pluginable coders, on Oct XX, 2017](https://github.com/rs/SDWebImage/releases/tag/4.2.0)
|
||||
See [all tickets marked for the 4.2.0 release](https://github.com/rs/SDWebImage/milestone/16)
|
||||
|
||||
#### Features
|
||||
- Refactor decoding code and provide decoding plugin #1991
|
||||
- HEIC format support #2080 #1853 #2038
|
||||
- Welcome back our previous `UIImage+GIF` category for animated GIF! Not enabled by default. #2064
|
||||
- Add the animated GIF encoding support for `SDWebImageGIFCoder` on `macOS` (use `NSImage` API) #2067
|
||||
- Implemented `-[NSImage isGIF]` method to return whether current `NSImage` has GIF representation #2071
|
||||
- Allow user to provide reading options such as mapped file to improve performance in `SDImageCache` disk cache #2057
|
||||
- Add progressive image load for WebP images #1991 #1987 #1986
|
||||
- CI builds use Xcode 9
|
||||
- Fixed our tests and improved the code coverage #2068
|
||||
|
||||
#### Fixes
|
||||
- Fixed lost orientation issues #1991 #2034 #2026 #1014 #1040 #815
|
||||
- Fixed `UIImage(GIF) sd_animatedGIFWithData` crash #1991 #1837
|
||||
- Fixed progressive WebP height issue #2066
|
||||
- Fixed `SDWebImageManager.m __destroy_helper_block_` crash #2048 #1941
|
||||
- Fixed cached image filename are sometimes generated with invalid path extensions #2061
|
||||
- Fixed GIF performance problem #1901 by creating `FLAnimatedImage` instance on global queue #2047
|
||||
|
||||
#### Docs
|
||||
- Updated diagrams
|
||||
|
||||
## [4.1.2 - 4.1 patch, on Oct 9th, 2017](https://github.com/rs/SDWebImage/releases/tag/4.1.2)
|
||||
See [all tickets marked for the 4.1.2 release](https://github.com/rs/SDWebImage/milestone/17)
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
Pod::Spec.new do |s|
|
||||
s.name = 'SDWebImage'
|
||||
s.version = '4.1.2'
|
||||
s.version = '4.2.0'
|
||||
|
||||
s.osx.deployment_target = '10.8'
|
||||
s.ios.deployment_target = '7.0'
|
||||
|
|
|
@ -52,17 +52,25 @@
|
|||
options:options
|
||||
operationKey:nil
|
||||
setImageBlock:^(UIImage *image, NSData *imageData) {
|
||||
// This setImageBlock may not called from main queue
|
||||
SDImageFormat imageFormat = [NSData sd_imageFormatForImageData:imageData];
|
||||
FLAnimatedImage *animatedImage;
|
||||
if (imageFormat == SDImageFormatGIF) {
|
||||
weakSelf.animatedImage = [FLAnimatedImage animatedImageWithGIFData:imageData];
|
||||
weakSelf.image = nil;
|
||||
} else {
|
||||
weakSelf.image = image;
|
||||
weakSelf.animatedImage = nil;
|
||||
animatedImage = [FLAnimatedImage animatedImageWithGIFData:imageData];
|
||||
}
|
||||
dispatch_main_async_safe(^{
|
||||
if (animatedImage) {
|
||||
weakSelf.animatedImage = animatedImage;
|
||||
weakSelf.image = nil;
|
||||
} else {
|
||||
weakSelf.image = image;
|
||||
weakSelf.animatedImage = nil;
|
||||
}
|
||||
});
|
||||
}
|
||||
progress:progressBlock
|
||||
completed:completedBlock];
|
||||
completed:completedBlock
|
||||
context:@{SDWebImageInternalSetImageInGlobalQueueKey: @(YES)}];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -16,7 +16,8 @@ typedef NS_ENUM(NSInteger, SDImageFormat) {
|
|||
SDImageFormatPNG,
|
||||
SDImageFormatGIF,
|
||||
SDImageFormatTIFF,
|
||||
SDImageFormatWebP
|
||||
SDImageFormatWebP,
|
||||
SDImageFormatHEIC
|
||||
};
|
||||
|
||||
@interface NSData (ImageContentType)
|
||||
|
|
|
@ -14,6 +14,11 @@
|
|||
#import <MobileCoreServices/MobileCoreServices.h>
|
||||
#endif
|
||||
|
||||
// Currently Image/IO does not support WebP
|
||||
#define kSDUTTypeWebP ((__bridge CFStringRef)@"public.webp")
|
||||
// AVFileTypeHEIC is defined in AVFoundation via iOS 11, we use this without import AVFoundation
|
||||
#define kSDUTTypeHEIC ((__bridge CFStringRef)@"public.heic")
|
||||
|
||||
@implementation NSData (ImageContentType)
|
||||
|
||||
+ (SDImageFormat)sd_imageFormatForImageData:(nullable NSData *)data {
|
||||
|
@ -21,6 +26,7 @@
|
|||
return SDImageFormatUndefined;
|
||||
}
|
||||
|
||||
// File signatures table: http://www.garykessler.net/library/file_sigs.html
|
||||
uint8_t c;
|
||||
[data getBytes:&c length:1];
|
||||
switch (c) {
|
||||
|
@ -33,16 +39,26 @@
|
|||
case 0x49:
|
||||
case 0x4D:
|
||||
return SDImageFormatTIFF;
|
||||
case 0x52:
|
||||
// R as RIFF for WEBP
|
||||
if (data.length < 12) {
|
||||
return SDImageFormatUndefined;
|
||||
case 0x52: {
|
||||
if (data.length >= 12) {
|
||||
//RIFF....WEBP
|
||||
NSString *testString = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(0, 12)] encoding:NSASCIIStringEncoding];
|
||||
if ([testString hasPrefix:@"RIFF"] && [testString hasSuffix:@"WEBP"]) {
|
||||
return SDImageFormatWebP;
|
||||
}
|
||||
}
|
||||
|
||||
NSString *testString = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(0, 12)] encoding:NSASCIIStringEncoding];
|
||||
if ([testString hasPrefix:@"RIFF"] && [testString hasSuffix:@"WEBP"]) {
|
||||
return SDImageFormatWebP;
|
||||
break;
|
||||
}
|
||||
case 0x00: {
|
||||
if (data.length >= 12) {
|
||||
//....ftypheic
|
||||
NSString *testString = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(4, 8)] encoding:NSASCIIStringEncoding];
|
||||
if ([testString isEqualToString:@"ftypheic"]) {
|
||||
return SDImageFormatHEIC;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return SDImageFormatUndefined;
|
||||
}
|
||||
|
@ -62,6 +78,12 @@
|
|||
case SDImageFormatTIFF:
|
||||
UTType = kUTTypeTIFF;
|
||||
break;
|
||||
case SDImageFormatWebP:
|
||||
UTType = kSDUTTypeWebP;
|
||||
break;
|
||||
case SDImageFormatHEIC:
|
||||
UTType = kSDUTTypeHEIC;
|
||||
break;
|
||||
default:
|
||||
// default is kUTTypePNG
|
||||
UTType = kUTTypePNG;
|
||||
|
|
|
@ -23,7 +23,18 @@
|
|||
}
|
||||
|
||||
- (BOOL)isGIF {
|
||||
return NO;
|
||||
BOOL isGIF = NO;
|
||||
for (NSImageRep *rep in self.representations) {
|
||||
if ([rep isKindOfClass:[NSBitmapImageRep class]]) {
|
||||
NSBitmapImageRep *bitmapRep = (NSBitmapImageRep *)rep;
|
||||
NSUInteger frameCount = [[bitmapRep valueForProperty:NSImageFrameCount] unsignedIntegerValue];
|
||||
if (frameCount > 1) {
|
||||
isGIF = YES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return isGIF;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -174,10 +174,11 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
|
|||
}
|
||||
unsigned char r[CC_MD5_DIGEST_LENGTH];
|
||||
CC_MD5(str, (CC_LONG)strlen(str), r);
|
||||
NSURL *keyURL = [NSURL URLWithString:key];
|
||||
NSString *ext = keyURL ? keyURL.pathExtension : key.pathExtension;
|
||||
NSString *filename = [NSString stringWithFormat:@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%@",
|
||||
r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7], r[8], r[9], r[10],
|
||||
r[11], r[12], r[13], r[14], r[15], [key.pathExtension isEqualToString:@""] ? @"" : [NSString stringWithFormat:@".%@", key.pathExtension]];
|
||||
|
||||
r[11], r[12], r[13], r[14], r[15], ext.length == 0 ? @"" : [NSString stringWithFormat:@".%@", ext]];
|
||||
return filename;
|
||||
}
|
||||
|
||||
|
|
|
@ -33,10 +33,12 @@ CG_EXTERN BOOL SDCGImageRefContainsAlpha(_Nullable CGImageRef imageRef);
|
|||
|
||||
/**
|
||||
This is the image coder protocol to provide custom image decoding/encoding.
|
||||
These methods are all required to implement.
|
||||
@note Pay attention that these methods are not called from main queue.
|
||||
*/
|
||||
@protocol SDWebImageCoder <NSObject>
|
||||
|
||||
@required
|
||||
#pragma mark - Decoding
|
||||
/**
|
||||
Returns YES if this coder can decode some data. Otherwise, the data should be passed to another coder.
|
||||
|
@ -90,10 +92,12 @@ CG_EXTERN BOOL SDCGImageRefContainsAlpha(_Nullable CGImageRef imageRef);
|
|||
|
||||
/**
|
||||
This is the image coder protocol to provide custom progressive image decoding.
|
||||
These methods are all required to implement.
|
||||
@note Pay attention that these methods are not called from main queue.
|
||||
*/
|
||||
@protocol SDWebImageProgressiveCoder <SDWebImageCoder>
|
||||
|
||||
@required
|
||||
/**
|
||||
Returns YES if this coder can incremental decode some data. Otherwise, it should be passed to another coder.
|
||||
|
||||
|
|
|
@ -11,13 +11,13 @@
|
|||
|
||||
/**
|
||||
Global object holding the array of coders, so that we avoid passing them from object to object.
|
||||
Uses a priority queue behind scenes, which means the latest added coders have priority.
|
||||
Uses a priority queue behind scenes, which means the latest added coders have the highest priority.
|
||||
This is done so when encoding/decoding something, we go through the list and ask each coder if they can handle the current data.
|
||||
That way, users can add their custom coders while preserving our existing prebuilt ones
|
||||
|
||||
Note: the `coders` getter will return the coders in their reversed order
|
||||
Example:
|
||||
- by default we internally set coders = `IOCoder`, `WebPCoder`
|
||||
- by default we internally set coders = `IOCoder`, `WebPCoder`. (`GIFCoder` is not recommended to add only if you want to get GIF support without `FLAnimatedImage`)
|
||||
- calling `coders` will return `@[WebPCoder, IOCoder]`
|
||||
- call `[addCoder:[MyCrazyCoder new]]`
|
||||
- calling `coders` now returns `@[MyCrazyCoder, WebPCoder, IOCoder]`
|
||||
|
|
|
@ -332,6 +332,7 @@ didReceiveResponse:(NSURLResponse *)response
|
|||
if ([coder conformsToProtocol:@protocol(SDWebImageProgressiveCoder)] &&
|
||||
[((id<SDWebImageProgressiveCoder>)coder) canIncrementallyDecodeFromData:imageData]) {
|
||||
self.progressiveCoder = [[[coder class] alloc] init];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,8 @@
|
|||
Built in coder using ImageIO that supports GIF encoding/decoding
|
||||
@note `SDWebImageIOCoder` supports GIF but only as static (will use the 1st frame).
|
||||
@note Use `SDWebImageGIFCoder` for fully animated GIFs - less performant than `FLAnimatedImage`
|
||||
@note The recommended approach for animated GIFs is using `FLAnimatedImage`
|
||||
@note If you decide to make all `UIImageView`(including `FLAnimatedImageView`) instance support GIF. You should add this coder to `SDWebImageCodersManager` and make sure that it has a higher priority than `SDWebImageIOCoder`
|
||||
@note The recommended approach for animated GIFs is using `FLAnimatedImage`. It's more performant than `UIImageView` for GIF displaying
|
||||
*/
|
||||
@interface SDWebImageGIFCoder : NSObject <SDWebImageCoder>
|
||||
|
||||
|
|
|
@ -10,9 +10,15 @@
|
|||
#import "SDWebImageCoder.h"
|
||||
|
||||
/**
|
||||
Built in coder that supports PNG, JPEG, TIFF, includes support for progressive decoding
|
||||
Built in coder that supports PNG, JPEG, TIFF, includes support for progressive decoding.
|
||||
|
||||
GIF
|
||||
Also supports static GIF (meaning will only handle the 1st frame).
|
||||
For a full GIF support, we recommend `FLAnimatedImage` or our less performant `SDWebImageGIFCoder`
|
||||
|
||||
HEIC
|
||||
This coder also supports HEIC format because ImageIO supports it natively. But it depends on the system capabilities, so it won't work on all devices.
|
||||
Hardware works if: (iOS 11 || macOS 10.13) && (isMac || isIPhoneAndA10FusionChipAbove) && (!Simulator)
|
||||
*/
|
||||
@interface SDWebImageImageIOCoder : NSObject <SDWebImageProgressiveCoder>
|
||||
|
||||
|
|
|
@ -66,8 +66,8 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over
|
|||
#pragma mark - Decode
|
||||
- (BOOL)canDecodeFromData:(nullable NSData *)data {
|
||||
switch ([NSData sd_imageFormatForImageData:data]) {
|
||||
// Do not support WebP decoding
|
||||
case SDImageFormatWebP:
|
||||
// Do not support WebP decoding
|
||||
return NO;
|
||||
default:
|
||||
return YES;
|
||||
|
@ -76,8 +76,8 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over
|
|||
|
||||
- (BOOL)canIncrementallyDecodeFromData:(NSData *)data {
|
||||
switch ([NSData sd_imageFormatForImageData:data]) {
|
||||
// Support static GIF progressive decoding
|
||||
case SDImageFormatWebP:
|
||||
// Do not support WebP progressive decoding
|
||||
return NO;
|
||||
default:
|
||||
return YES;
|
||||
|
@ -100,7 +100,7 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over
|
|||
|
||||
SDImageFormat format = [NSData sd_imageFormatForImageData:data];
|
||||
if (format == SDImageFormatGIF) {
|
||||
// static single GIF need to be created animated for FLAnimatedImageView logic
|
||||
// static single GIF need to be created animated for `FLAnimatedImage` logic
|
||||
// GIF does not support EXIF image orientation
|
||||
image = [UIImage animatedImageWithImages:@[image] duration:image.duration];
|
||||
return image;
|
||||
|
@ -213,7 +213,16 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over
|
|||
if (!shouldScaleDown) {
|
||||
return [self sd_decompressedImageWithImage:image];
|
||||
} else {
|
||||
return [self sd_decompressedAndScaledDownImageWithImage:image];
|
||||
UIImage *scaledDownImage = [self sd_decompressedAndScaledDownImageWithImage:image];
|
||||
if (scaledDownImage && !CGSizeEqualToSize(scaledDownImage.size, image.size)) {
|
||||
// if the image is scaled down, need to modify the data pointer as well
|
||||
SDImageFormat format = [NSData sd_imageFormatForImageData:*data];
|
||||
NSData *imageData = [self encodedDataWithImage:scaledDownImage format:format];
|
||||
if (imageData) {
|
||||
*data = imageData;
|
||||
}
|
||||
}
|
||||
return scaledDownImage;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -385,9 +394,12 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over
|
|||
#pragma mark - Encode
|
||||
- (BOOL)canEncodeToFormat:(SDImageFormat)format {
|
||||
switch (format) {
|
||||
// Do not support WebP encoding
|
||||
case SDImageFormatWebP:
|
||||
// Do not support WebP encoding
|
||||
return NO;
|
||||
case SDImageFormatHEIC:
|
||||
// Check HEIC encoding compatibility
|
||||
return [[self class] canEncodeToHEICFormat];
|
||||
default:
|
||||
return YES;
|
||||
}
|
||||
|
@ -460,6 +472,27 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over
|
|||
return YES;
|
||||
}
|
||||
|
||||
+ (BOOL)canEncodeToHEICFormat {
|
||||
static BOOL canEncode = NO;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
NSMutableData *imageData = [NSMutableData data];
|
||||
CFStringRef imageUTType = [NSData sd_UTTypeFromSDImageFormat:SDImageFormatHEIC];
|
||||
|
||||
// Create an image destination.
|
||||
CGImageDestinationRef imageDestination = CGImageDestinationCreateWithData((__bridge CFMutableDataRef)imageData, imageUTType, 1, NULL);
|
||||
if (!imageDestination) {
|
||||
// Can't encode to HEIC
|
||||
canEncode = NO;
|
||||
} else {
|
||||
// Can encode to HEIC
|
||||
CFRelease(imageDestination);
|
||||
canEncode = YES;
|
||||
}
|
||||
});
|
||||
return canEncode;
|
||||
}
|
||||
|
||||
#if SD_UIKIT || SD_WATCH
|
||||
#pragma mark EXIF orientation tag converter
|
||||
+ (UIImageOrientation)sd_imageOrientationFromImageData:(nonnull NSData *)imageData {
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
|
||||
#import "SDWebImageManager.h"
|
||||
|
||||
FOUNDATION_EXPORT NSString * _Nonnull const SDWebImageInternalSetImageInGlobalQueueKey;
|
||||
|
||||
typedef void(^SDSetImageBlock)(UIImage * _Nullable image, NSData * _Nullable imageData);
|
||||
|
||||
@interface UIView (WebCache)
|
||||
|
@ -50,6 +52,34 @@ typedef void(^SDSetImageBlock)(UIImage * _Nullable image, NSData * _Nullable ima
|
|||
progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
|
||||
completed:(nullable SDExternalCompletionBlock)completedBlock;
|
||||
|
||||
/**
|
||||
* Set the imageView `image` with an `url` and optionally a placeholder image.
|
||||
*
|
||||
* The download is asynchronous and cached.
|
||||
*
|
||||
* @param url The url for the image.
|
||||
* @param placeholder The image to be set initially, until the image request finishes.
|
||||
* @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values.
|
||||
* @param operationKey A string to be used as the operation key. If nil, will use the class name
|
||||
* @param setImageBlock Block used for custom set image code
|
||||
* @param progressBlock A block called while image is downloading
|
||||
* @note the progress block is executed on a background queue
|
||||
* @param completedBlock A block called when operation has been completed. This block has no return value
|
||||
* and takes the requested UIImage as first parameter. In case of error the image parameter
|
||||
* is nil and the second parameter may contain an NSError. The third parameter is a Boolean
|
||||
* indicating if the image was retrieved from the local cache or from the network.
|
||||
* The fourth parameter is the original image url.
|
||||
* @param context A context with extra information to perform specify changes or processes.
|
||||
*/
|
||||
- (void)sd_internalSetImageWithURL:(nullable NSURL *)url
|
||||
placeholderImage:(nullable UIImage *)placeholder
|
||||
options:(SDWebImageOptions)options
|
||||
operationKey:(nullable NSString *)operationKey
|
||||
setImageBlock:(nullable SDSetImageBlock)setImageBlock
|
||||
progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
|
||||
completed:(nullable SDExternalCompletionBlock)completedBlock
|
||||
context:(nullable NSDictionary *)context;
|
||||
|
||||
/**
|
||||
* Cancel the current download
|
||||
*/
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
#import "objc/runtime.h"
|
||||
#import "UIView+WebCacheOperation.h"
|
||||
|
||||
NSString * const SDWebImageInternalSetImageInGlobalQueueKey = @"setImageInGlobalQueue";
|
||||
|
||||
static char imageURLKey;
|
||||
|
||||
#if SD_UIKIT
|
||||
|
@ -34,6 +36,17 @@ static char TAG_ACTIVITY_SHOW;
|
|||
setImageBlock:(nullable SDSetImageBlock)setImageBlock
|
||||
progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
|
||||
completed:(nullable SDExternalCompletionBlock)completedBlock {
|
||||
return [self sd_internalSetImageWithURL:url placeholderImage:placeholder options:options operationKey:operationKey setImageBlock:setImageBlock progress:progressBlock completed:completedBlock context:nil];
|
||||
}
|
||||
|
||||
- (void)sd_internalSetImageWithURL:(nullable NSURL *)url
|
||||
placeholderImage:(nullable UIImage *)placeholder
|
||||
options:(SDWebImageOptions)options
|
||||
operationKey:(nullable NSString *)operationKey
|
||||
setImageBlock:(nullable SDSetImageBlock)setImageBlock
|
||||
progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
|
||||
completed:(nullable SDExternalCompletionBlock)completedBlock
|
||||
context:(nullable NSDictionary *)context {
|
||||
NSString *validOperationKey = operationKey ?: NSStringFromClass([self class]);
|
||||
[self sd_cancelImageLoadOperationWithKey:validOperationKey];
|
||||
objc_setAssociatedObject(self, &imageURLKey, url, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
|
@ -54,28 +67,48 @@ static char TAG_ACTIVITY_SHOW;
|
|||
id <SDWebImageOperation> operation = [SDWebImageManager.sharedManager loadImageWithURL:url options:options progress:progressBlock completed:^(UIImage *image, NSData *data, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
|
||||
__strong __typeof (wself) sself = wself;
|
||||
[sself sd_removeActivityIndicator];
|
||||
if (!sself) {
|
||||
if (!sself) { return; }
|
||||
BOOL shouldCallCompletedBlock = finished || (options & SDWebImageAvoidAutoSetImage);
|
||||
BOOL shouldNotSetImage = ((image && (options & SDWebImageAvoidAutoSetImage)) ||
|
||||
(!image && !(options & SDWebImageDelayPlaceholder)));
|
||||
SDWebImageNoParamsBlock callCompletedBlockClojure = ^{
|
||||
if (!sself) { return; }
|
||||
if (!shouldNotSetImage) {
|
||||
[sself sd_setNeedsLayout];
|
||||
}
|
||||
if (completedBlock && shouldCallCompletedBlock) {
|
||||
completedBlock(image, error, cacheType, url);
|
||||
}
|
||||
};
|
||||
|
||||
// case 1a: we got an image, but the SDWebImageAvoidAutoSetImage flag is set
|
||||
// OR
|
||||
// case 1b: we got no image and the SDWebImageDelayPlaceholder is not set
|
||||
if (shouldNotSetImage) {
|
||||
dispatch_main_async_safe(callCompletedBlockClojure);
|
||||
return;
|
||||
}
|
||||
dispatch_main_async_safe(^{
|
||||
if (!sself) {
|
||||
return;
|
||||
}
|
||||
if (image && (options & SDWebImageAvoidAutoSetImage) && completedBlock) {
|
||||
completedBlock(image, error, cacheType, url);
|
||||
return;
|
||||
} else if (image) {
|
||||
[sself sd_setImage:image imageData:data basedOnClassOrViaCustomSetImageBlock:setImageBlock];
|
||||
[sself sd_setNeedsLayout];
|
||||
} else {
|
||||
if ((options & SDWebImageDelayPlaceholder)) {
|
||||
[sself sd_setImage:placeholder imageData:nil basedOnClassOrViaCustomSetImageBlock:setImageBlock];
|
||||
[sself sd_setNeedsLayout];
|
||||
}
|
||||
}
|
||||
if (completedBlock && finished) {
|
||||
completedBlock(image, error, cacheType, url);
|
||||
}
|
||||
|
||||
UIImage *targetImage = nil;
|
||||
NSData *targetData = nil;
|
||||
if (image) {
|
||||
// case 2a: we got an image and the SDWebImageAvoidAutoSetImage is not set
|
||||
targetImage = image;
|
||||
targetData = data;
|
||||
} else if (options & SDWebImageDelayPlaceholder) {
|
||||
// case 2b: we got no image and the SDWebImageDelayPlaceholder flag is set
|
||||
targetImage = placeholder;
|
||||
targetData = nil;
|
||||
}
|
||||
BOOL shouldUseGlobalQueue = NO;
|
||||
if (context && [context valueForKey:SDWebImageInternalSetImageInGlobalQueueKey]) {
|
||||
shouldUseGlobalQueue = [[context valueForKey:SDWebImageInternalSetImageInGlobalQueueKey] boolValue];
|
||||
}
|
||||
dispatch_queue_t targetQueue = shouldUseGlobalQueue ? dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0) : dispatch_get_main_queue();
|
||||
|
||||
dispatch_async(targetQueue, ^{
|
||||
[sself sd_setImage:targetImage imageData:targetData basedOnClassOrViaCustomSetImageBlock:setImageBlock];
|
||||
dispatch_main_async_safe(callCompletedBlockClojure);
|
||||
});
|
||||
}];
|
||||
[self sd_setImageLoadOperation:operation forKey:validOperationKey];
|
||||
|
|
|
@ -218,6 +218,19 @@ NSString *kImageTestKey = @"TestImageKey.jpg";
|
|||
[self waitForExpectationsWithCommonTimeout];
|
||||
}
|
||||
|
||||
- (void)test34CachePathForSimpleKeyWithExtension {
|
||||
NSString *cachePath = [[SDImageCache sharedImageCache] cachePathForKey:kTestJpegURL inPath:@""];
|
||||
expect(cachePath).toNot.beNil();
|
||||
expect([cachePath pathExtension]).to.equal(@"jpg");
|
||||
}
|
||||
|
||||
- (void)test35CachePathForKeyWithDotButNoExtension {
|
||||
NSString *urlString = @"https://maps.googleapis.com/maps/api/staticmap?center=48.8566,2.3522&format=png&maptype=roadmap&scale=2&size=375x200&zoom=15";
|
||||
NSString *cachePath = [[SDImageCache sharedImageCache] cachePathForKey:urlString inPath:@""];
|
||||
expect(cachePath).toNot.beNil();
|
||||
expect([cachePath pathExtension]).to.equal(@"");
|
||||
}
|
||||
|
||||
- (void)test40InsertionOfImageData {
|
||||
XCTestExpectation *expectation = [self expectationWithDescription:@"Insertion of image data works"];
|
||||
|
||||
|
|
|
@ -15,11 +15,11 @@
|
|||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>4.1.2</string>
|
||||
<string>4.2.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>4.1.2</string>
|
||||
<string>4.2.0</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string></string>
|
||||
</dict>
|
||||
|
|
Loading…
Reference in New Issue