Merge pull request #1217 from mythodeia/master
Import fixes from @mythodeia 's fork
This commit is contained in:
commit
be560a4090
|
@ -379,6 +379,9 @@
|
|||
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
|
||||
}
|
||||
|
||||
[cell.imageView setShowActivityIndicatorView:YES];
|
||||
[cell.imageView setIndicatorStyle:UIActivityIndicatorViewStyleGray];
|
||||
|
||||
cell.textLabel.text = [NSString stringWithFormat:@"Image #%ld", (long)indexPath.row];
|
||||
cell.imageView.contentMode = UIViewContentModeScaleAspectFill;
|
||||
[cell.imageView sd_setImageWithURL:[NSURL URLWithString:[_objects objectAtIndex:indexPath.row]]
|
||||
|
|
|
@ -42,6 +42,16 @@ typedef void(^SDWebImageCalculateSizeBlock)(NSUInteger fileCount, NSUInteger tot
|
|||
*/
|
||||
@property (assign, nonatomic) BOOL shouldDecompressImages;
|
||||
|
||||
/**
|
||||
* disable iCloud backup [defaults to YES]
|
||||
*/
|
||||
@property (assign, nonatomic) BOOL shouldDisableiCloud;
|
||||
|
||||
/**
|
||||
* use memory cache [defaults to YES]
|
||||
*/
|
||||
@property (assign, nonatomic) BOOL shouldCacheImagesInMemory;
|
||||
|
||||
/**
|
||||
* The maximum "total cost" of the in-memory image cache. The cost function is the number of pixels held in memory.
|
||||
*/
|
||||
|
|
|
@ -116,6 +116,12 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
|
|||
// Set decompression to YES
|
||||
_shouldDecompressImages = YES;
|
||||
|
||||
// memory cache enabled
|
||||
_shouldCacheImagesInMemory = YES;
|
||||
|
||||
// Disable iCloud
|
||||
_shouldDisableiCloud = YES;
|
||||
|
||||
dispatch_sync(_ioQueue, ^{
|
||||
_fileManager = [NSFileManager new];
|
||||
});
|
||||
|
@ -193,9 +199,11 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
|
|||
if (!image || !key) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSUInteger cost = SDCacheCostForImage(image);
|
||||
[self.memCache setObject:image forKey:key cost:cost];
|
||||
// if memory cache is enabled
|
||||
if (self.shouldCacheImagesInMemory) {
|
||||
NSUInteger cost = SDCacheCostForImage(image);
|
||||
[self.memCache setObject:image forKey:key cost:cost];
|
||||
}
|
||||
|
||||
if (toDisk) {
|
||||
dispatch_async(self.ioQueue, ^{
|
||||
|
@ -237,7 +245,17 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
|
|||
[_fileManager createDirectoryAtPath:_diskCachePath withIntermediateDirectories:YES attributes:nil error:NULL];
|
||||
}
|
||||
|
||||
[_fileManager createFileAtPath:[self defaultCachePathForKey:key] contents:data attributes:nil];
|
||||
// get cache Path for image key
|
||||
NSString *cachePathForKey = [self defaultCachePathForKey:key];
|
||||
// transform to NSUrl
|
||||
NSURL *fileURL = [NSURL fileURLWithPath:cachePathForKey];
|
||||
|
||||
[_fileManager createFileAtPath:cachePathForKey contents:data attributes:nil];
|
||||
|
||||
// disable iCloud backup
|
||||
if (self.shouldDisableiCloud) {
|
||||
[fileURL setResourceValue:[NSNumber numberWithBool:YES] forKey:NSURLIsExcludedFromBackupKey error:nil];
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -277,6 +295,7 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
|
|||
}
|
||||
|
||||
- (UIImage *)imageFromDiskCacheForKey:(NSString *)key {
|
||||
|
||||
// First check the in-memory cache...
|
||||
UIImage *image = [self imageFromMemoryCacheForKey:key];
|
||||
if (image) {
|
||||
|
@ -285,7 +304,7 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
|
|||
|
||||
// Second check the disk cache...
|
||||
UIImage *diskImage = [self diskImageForKey:key];
|
||||
if (diskImage) {
|
||||
if (diskImage && self.shouldCacheImagesInMemory) {
|
||||
NSUInteger cost = SDCacheCostForImage(diskImage);
|
||||
[self.memCache setObject:diskImage forKey:key cost:cost];
|
||||
}
|
||||
|
@ -356,7 +375,7 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
|
|||
|
||||
@autoreleasepool {
|
||||
UIImage *diskImage = [self diskImageForKey:key];
|
||||
if (diskImage) {
|
||||
if (diskImage && self.shouldCacheImagesInMemory) {
|
||||
NSUInteger cost = SDCacheCostForImage(diskImage);
|
||||
[self.memCache setObject:diskImage forKey:key cost:cost];
|
||||
}
|
||||
|
@ -387,9 +406,11 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
|
|||
if (key == nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
[self.memCache removeObjectForKey:key];
|
||||
|
||||
|
||||
if (self.shouldCacheImagesInMemory) {
|
||||
[self.memCache removeObjectForKey:key];
|
||||
}
|
||||
|
||||
if (fromDisk) {
|
||||
dispatch_async(self.ioQueue, ^{
|
||||
[_fileManager removeItemAtPath:[self defaultCachePathForKey:key] error:nil];
|
||||
|
|
|
@ -28,7 +28,7 @@ inline UIImage *SDScaledImageForKey(NSString *key, UIImage *image) {
|
|||
}
|
||||
else {
|
||||
if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {
|
||||
CGFloat scale = 1.0;
|
||||
CGFloat scale = [UIScreen mainScreen].scale;
|
||||
if (key.length >= 8) {
|
||||
NSRange range = [key rangeOfString:@"@2x."];
|
||||
if (range.location != NSNotFound) {
|
||||
|
|
|
@ -13,60 +13,38 @@
|
|||
@implementation UIImage (ForceDecode)
|
||||
|
||||
+ (UIImage *)decodedImageWithImage:(UIImage *)image {
|
||||
if (image.images) {
|
||||
// Do not decode animated images
|
||||
return image;
|
||||
}
|
||||
// do not decode animated images
|
||||
if (image.images) { return image; }
|
||||
|
||||
CGImageRef imageRef = image.CGImage;
|
||||
CGSize imageSize = CGSizeMake(CGImageGetWidth(imageRef), CGImageGetHeight(imageRef));
|
||||
CGRect imageRect = (CGRect){.origin = CGPointZero, .size = imageSize};
|
||||
|
||||
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
|
||||
CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
|
||||
CGImageAlphaInfo alpha = CGImageGetAlphaInfo(imageRef);
|
||||
BOOL anyAlpha = (alpha == kCGImageAlphaFirst ||
|
||||
alpha == kCGImageAlphaLast ||
|
||||
alpha == kCGImageAlphaPremultipliedFirst ||
|
||||
alpha == kCGImageAlphaPremultipliedLast);
|
||||
|
||||
int infoMask = (bitmapInfo & kCGBitmapAlphaInfoMask);
|
||||
BOOL anyNonAlpha = (infoMask == kCGImageAlphaNone ||
|
||||
infoMask == kCGImageAlphaNoneSkipFirst ||
|
||||
infoMask == kCGImageAlphaNoneSkipLast);
|
||||
if (anyAlpha) { return image; }
|
||||
|
||||
// CGBitmapContextCreate doesn't support kCGImageAlphaNone with RGB.
|
||||
// https://developer.apple.com/library/mac/#qa/qa1037/_index.html
|
||||
if (infoMask == kCGImageAlphaNone && CGColorSpaceGetNumberOfComponents(colorSpace) > 1) {
|
||||
// Unset the old alpha info.
|
||||
bitmapInfo &= ~kCGBitmapAlphaInfoMask;
|
||||
size_t width = CGImageGetWidth(imageRef);
|
||||
size_t height = CGImageGetHeight(imageRef);
|
||||
|
||||
// Set noneSkipFirst.
|
||||
bitmapInfo |= kCGImageAlphaNoneSkipFirst;
|
||||
}
|
||||
// Some PNGs tell us they have alpha but only 3 components. Odd.
|
||||
else if (!anyNonAlpha && CGColorSpaceGetNumberOfComponents(colorSpace) == 3) {
|
||||
// Unset the old alpha info.
|
||||
bitmapInfo &= ~kCGBitmapAlphaInfoMask;
|
||||
bitmapInfo |= kCGImageAlphaPremultipliedFirst;
|
||||
}
|
||||
CGContextRef context = CGBitmapContextCreate(NULL, width,
|
||||
height,
|
||||
CGImageGetBitsPerComponent(imageRef),
|
||||
0,
|
||||
CGImageGetColorSpace(imageRef),
|
||||
kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedFirst);
|
||||
|
||||
// It calculates the bytes-per-row based on the bitsPerComponent and width arguments.
|
||||
CGContextRef context = CGBitmapContextCreate(NULL,
|
||||
imageSize.width,
|
||||
imageSize.height,
|
||||
CGImageGetBitsPerComponent(imageRef),
|
||||
0,
|
||||
colorSpace,
|
||||
bitmapInfo);
|
||||
CGColorSpaceRelease(colorSpace);
|
||||
|
||||
// If failed, return undecompressed image
|
||||
if (!context) return image;
|
||||
|
||||
CGContextDrawImage(context, imageRect, imageRef);
|
||||
CGImageRef decompressedImageRef = CGBitmapContextCreateImage(context);
|
||||
// Draw the image into the context and retrieve the new image, which will now have an alpha layer
|
||||
CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
|
||||
CGImageRef imageRefWithAlpha = CGBitmapContextCreateImage(context);
|
||||
UIImage *imageWithAlpha = [UIImage imageWithCGImage:imageRefWithAlpha];
|
||||
|
||||
CGContextRelease(context);
|
||||
CGImageRelease(imageRefWithAlpha);
|
||||
|
||||
UIImage *decompressedImage = [UIImage imageWithCGImage:decompressedImageRef scale:image.scale orientation:image.imageOrientation];
|
||||
CGImageRelease(decompressedImageRef);
|
||||
return decompressedImage;
|
||||
return imageWithAlpha;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -176,6 +176,18 @@
|
|||
|
||||
- (void)sd_cancelCurrentAnimationImagesLoad;
|
||||
|
||||
/**
|
||||
* Show activity UIActivityIndicatorView
|
||||
*/
|
||||
- (void)setShowActivityIndicatorView:(BOOL)show;
|
||||
|
||||
/**
|
||||
* set desired UIActivityIndicatorViewStyle
|
||||
*
|
||||
* @param style The style of the UIActivityIndicatorView
|
||||
*/
|
||||
- (void)setIndicatorStyle:(UIActivityIndicatorViewStyle)style;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
|
|
@ -11,6 +11,9 @@
|
|||
#import "UIView+WebCacheOperation.h"
|
||||
|
||||
static char imageURLKey;
|
||||
static char TAG_ACTIVITY_INDICATOR;
|
||||
static char TAG_ACTIVITY_STYLE;
|
||||
static char TAG_ACTIVITY_SHOW;
|
||||
|
||||
@implementation UIImageView (WebCache)
|
||||
|
||||
|
@ -49,8 +52,15 @@ static char imageURLKey;
|
|||
}
|
||||
|
||||
if (url) {
|
||||
|
||||
// check if activityView is enabled or not
|
||||
if ([self showActivityIndicatorView]) {
|
||||
[self addActivityIndicator];
|
||||
}
|
||||
|
||||
__weak __typeof(self)wself = self;
|
||||
id <SDWebImageOperation> operation = [SDWebImageManager.sharedManager downloadImageWithURL:url options:options progress:progressBlock completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
|
||||
[wself removeActivityIndicator];
|
||||
if (!wself) return;
|
||||
dispatch_main_sync_safe(^{
|
||||
if (!wself) return;
|
||||
|
@ -76,6 +86,7 @@ static char imageURLKey;
|
|||
[self sd_setImageLoadOperation:operation forKey:@"UIImageViewImageLoad"];
|
||||
} else {
|
||||
dispatch_main_async_safe(^{
|
||||
[self removeActivityIndicator];
|
||||
NSError *error = [NSError errorWithDomain:SDWebImageErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey : @"Trying to load a nil url"}];
|
||||
if (completedBlock) {
|
||||
completedBlock(nil, error, SDImageCacheTypeNone, url);
|
||||
|
@ -134,6 +145,70 @@ static char imageURLKey;
|
|||
[self sd_cancelImageLoadOperationWithKey:@"UIImageViewAnimationImages"];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
- (UIActivityIndicatorView *)activityIndicator {
|
||||
return (UIActivityIndicatorView *)objc_getAssociatedObject(self, &TAG_ACTIVITY_INDICATOR);
|
||||
}
|
||||
|
||||
- (void)setActivityIndicator:(UIActivityIndicatorView *)activityIndicator {
|
||||
objc_setAssociatedObject(self, &TAG_ACTIVITY_INDICATOR, activityIndicator, OBJC_ASSOCIATION_RETAIN);
|
||||
}
|
||||
|
||||
- (void)setShowActivityIndicatorView:(BOOL)show{
|
||||
objc_setAssociatedObject(self, &TAG_ACTIVITY_SHOW, [NSNumber numberWithBool:show], OBJC_ASSOCIATION_RETAIN);
|
||||
}
|
||||
|
||||
- (BOOL)showActivityIndicatorView{
|
||||
return [objc_getAssociatedObject(self, &TAG_ACTIVITY_SHOW) boolValue];
|
||||
}
|
||||
|
||||
- (void)setIndicatorStyle:(UIActivityIndicatorViewStyle)style{
|
||||
objc_setAssociatedObject(self, &TAG_ACTIVITY_STYLE, [NSNumber numberWithInt:style], OBJC_ASSOCIATION_RETAIN);
|
||||
}
|
||||
|
||||
- (int)getIndicatorStyle{
|
||||
return [objc_getAssociatedObject(self, &TAG_ACTIVITY_STYLE) intValue];
|
||||
}
|
||||
|
||||
- (void)addActivityIndicator {
|
||||
if (!self.activityIndicator) {
|
||||
self.activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:[self getIndicatorStyle]];
|
||||
self.activityIndicator.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
|
||||
dispatch_main_async_safe(^{
|
||||
[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]];
|
||||
});
|
||||
}
|
||||
|
||||
dispatch_main_async_safe(^{
|
||||
[self.activityIndicator startAnimating];
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
- (void)removeActivityIndicator {
|
||||
if (self.activityIndicator) {
|
||||
[self.activityIndicator removeFromSuperview];
|
||||
self.activityIndicator = nil;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue