From dcde40fc01d2815070a2b4b496234aeb1b6d038e Mon Sep 17 00:00:00 2001 From: mythodeia Date: Wed, 15 Jul 2015 10:43:29 +0300 Subject: [PATCH 1/5] set as default the device's screen scale --- SDWebImage/SDWebImageCompat.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SDWebImage/SDWebImageCompat.m b/SDWebImage/SDWebImageCompat.m index 54fb60eb4..9a011bc02 100644 --- a/SDWebImage/SDWebImageCompat.m +++ b/SDWebImage/SDWebImageCompat.m @@ -28,7 +28,7 @@ } 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) { From 4cfb12c01cef5e4f45aa1215d38afcbb2381b594 Mon Sep 17 00:00:00 2001 From: mythodeia Date: Wed, 15 Jul 2015 10:45:31 +0300 Subject: [PATCH 2/5] fix unsupported parameter combination issues when CGBitmapContextCreate is called --- SDWebImage/SDWebImageDecoder.m | 66 ++++++++++++---------------------- 1 file changed, 22 insertions(+), 44 deletions(-) diff --git a/SDWebImage/SDWebImageDecoder.m b/SDWebImage/SDWebImageDecoder.m index 79ddb30f6..b8d2fd6ca 100644 --- a/SDWebImage/SDWebImageDecoder.m +++ b/SDWebImage/SDWebImageDecoder.m @@ -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 From c68d585e4957175402c521c52fc72fc932fec86d Mon Sep 17 00:00:00 2001 From: mythodeia Date: Wed, 15 Jul 2015 10:50:04 +0300 Subject: [PATCH 3/5] activity indicator added ``` [cell.imageView setShowActivityIndicatorView:YES]; [cell.imageView setIndicatorStyle:UIActivityIndicatorViewStyleGray]; ``` --- .../SDWebImage Demo/MasterViewController.m | 3 + SDWebImage/UIImageView+WebCache.h | 12 +++ SDWebImage/UIImageView+WebCache.m | 75 +++++++++++++++++++ 3 files changed, 90 insertions(+) diff --git a/Examples/SDWebImage Demo/MasterViewController.m b/Examples/SDWebImage Demo/MasterViewController.m index daf90c51d..27dc465df 100644 --- a/Examples/SDWebImage Demo/MasterViewController.m +++ b/Examples/SDWebImage Demo/MasterViewController.m @@ -379,6 +379,9 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N 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]] diff --git a/SDWebImage/UIImageView+WebCache.h b/SDWebImage/UIImageView+WebCache.h index e7489f438..8ac420855 100644 --- a/SDWebImage/UIImageView+WebCache.h +++ b/SDWebImage/UIImageView+WebCache.h @@ -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 diff --git a/SDWebImage/UIImageView+WebCache.m b/SDWebImage/UIImageView+WebCache.m index 162c49af9..57656975e 100644 --- a/SDWebImage/UIImageView+WebCache.m +++ b/SDWebImage/UIImageView+WebCache.m @@ -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 @@ - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder } if (url) { + + // check if activityView is enabled or not + if ([self showActivityIndicatorView]) { + [self addActivityIndicator]; + } + __weak __typeof(self)wself = self; id 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 @@ - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder [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 @@ - (void)sd_cancelCurrentAnimationImagesLoad { [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 From a9ea132874e11dd5165db9858fad1729c272de0c Mon Sep 17 00:00:00 2001 From: mythodeia Date: Wed, 15 Jul 2015 11:04:44 +0300 Subject: [PATCH 4/5] disable iCloud backup --- SDWebImage/SDImageCache.h | 5 +++++ SDWebImage/SDImageCache.m | 15 ++++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/SDWebImage/SDImageCache.h b/SDWebImage/SDImageCache.h index 8e08aa154..ca6033a50 100644 --- a/SDWebImage/SDImageCache.h +++ b/SDWebImage/SDImageCache.h @@ -42,6 +42,11 @@ typedef void(^SDWebImageCalculateSizeBlock)(NSUInteger fileCount, NSUInteger tot */ @property (assign, nonatomic) BOOL shouldDecompressImages; +/** + * disable iCloud backup [defaults to YES] + */ +@property (assign, nonatomic) BOOL shouldDisableiCloud; + /** * The maximum "total cost" of the in-memory image cache. The cost function is the number of pixels held in memory. */ diff --git a/SDWebImage/SDImageCache.m b/SDWebImage/SDImageCache.m index 22026027d..c197b5c38 100644 --- a/SDWebImage/SDImageCache.m +++ b/SDWebImage/SDImageCache.m @@ -116,6 +116,9 @@ - (id)initWithNamespace:(NSString *)ns diskCacheDirectory:(NSString *)directory // Set decompression to YES _shouldDecompressImages = YES; + // Disable iCloud + _shouldDisableiCloud = YES; + dispatch_sync(_ioQueue, ^{ _fileManager = [NSFileManager new]; }); @@ -237,7 +240,17 @@ - (void)storeImage:(UIImage *)image recalculateFromImage:(BOOL)recalculate 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]; + } } }); } From df751e737b0236c942a3f9e10f63c968b2d54fdd Mon Sep 17 00:00:00 2001 From: mythodeia Date: Wed, 15 Jul 2015 11:35:03 +0300 Subject: [PATCH 5/5] added option to disable memory cache use this: ```shouldDisableMemoryCache``` to toggle memory cache --- SDWebImage/SDImageCache.h | 5 +++++ SDWebImage/SDImageCache.m | 24 ++++++++++++++++-------- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/SDWebImage/SDImageCache.h b/SDWebImage/SDImageCache.h index ca6033a50..2bbb902a4 100644 --- a/SDWebImage/SDImageCache.h +++ b/SDWebImage/SDImageCache.h @@ -47,6 +47,11 @@ typedef void(^SDWebImageCalculateSizeBlock)(NSUInteger fileCount, NSUInteger tot */ @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. */ diff --git a/SDWebImage/SDImageCache.m b/SDWebImage/SDImageCache.m index c197b5c38..f5ab18e98 100644 --- a/SDWebImage/SDImageCache.m +++ b/SDWebImage/SDImageCache.m @@ -116,6 +116,9 @@ - (id)initWithNamespace:(NSString *)ns diskCacheDirectory:(NSString *)directory // Set decompression to YES _shouldDecompressImages = YES; + // memory cache enabled + _shouldCacheImagesInMemory = YES; + // Disable iCloud _shouldDisableiCloud = YES; @@ -196,9 +199,11 @@ - (void)storeImage:(UIImage *)image recalculateFromImage:(BOOL)recalculate 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, ^{ @@ -290,6 +295,7 @@ - (UIImage *)imageFromMemoryCacheForKey:(NSString *)key { } - (UIImage *)imageFromDiskCacheForKey:(NSString *)key { + // First check the in-memory cache... UIImage *image = [self imageFromMemoryCacheForKey:key]; if (image) { @@ -298,7 +304,7 @@ - (UIImage *)imageFromDiskCacheForKey:(NSString *)key { // 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]; } @@ -369,7 +375,7 @@ - (NSOperation *)queryDiskCacheForKey:(NSString *)key done:(SDWebImageQueryCompl @autoreleasepool { UIImage *diskImage = [self diskImageForKey:key]; - if (diskImage) { + if (diskImage && self.shouldCacheImagesInMemory) { NSUInteger cost = SDCacheCostForImage(diskImage); [self.memCache setObject:diskImage forKey:key cost:cost]; } @@ -400,9 +406,11 @@ - (void)removeImageForKey:(NSString *)key fromDisk:(BOOL)fromDisk withCompletion 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];