ios pod reinstall

This commit is contained in:
Feruz 2018-12-16 20:17:13 +02:00
parent c51449fd01
commit 409eb17067
21 changed files with 364 additions and 261 deletions

View File

@ -17,50 +17,50 @@ PODS:
- glog
- glog (0.3.5)
- QBImagePickerController (3.4.0)
- React (0.57.7):
- React/Core (= 0.57.7)
- React (0.57.8):
- React/Core (= 0.57.8)
- react-native-fast-image (4.0.14):
- FLAnimatedImage
- React
- SDWebImage/Core
- SDWebImage/GIF
- React/Core (0.57.7):
- yoga (= 0.57.7.React)
- React/CxxBridge (0.57.7):
- React/Core (0.57.8):
- yoga (= 0.57.8.React)
- React/CxxBridge (0.57.8):
- Folly (= 2016.10.31.00)
- React/Core
- React/cxxreact
- React/cxxreact (0.57.7):
- React/cxxreact (0.57.8):
- boost-for-react-native (= 1.63.0)
- Folly (= 2016.10.31.00)
- React/jschelpers
- React/jsinspector
- React/DevSupport (0.57.7):
- React/DevSupport (0.57.8):
- React/Core
- React/RCTWebSocket
- React/fishhook (0.57.7)
- React/jschelpers (0.57.7):
- React/fishhook (0.57.8)
- React/jschelpers (0.57.8):
- Folly (= 2016.10.31.00)
- React/PrivateDatabase
- React/jsinspector (0.57.7)
- React/PrivateDatabase (0.57.7)
- React/RCTActionSheet (0.57.7):
- React/jsinspector (0.57.8)
- React/PrivateDatabase (0.57.8)
- React/RCTActionSheet (0.57.8):
- React/Core
- React/RCTAnimation (0.57.7):
- React/RCTAnimation (0.57.8):
- React/Core
- React/RCTBlob (0.57.7):
- React/RCTBlob (0.57.8):
- React/Core
- React/RCTCameraRoll (0.57.7):
- React/RCTCameraRoll (0.57.8):
- React/Core
- React/RCTImage
- React/RCTImage (0.57.7):
- React/RCTImage (0.57.8):
- React/Core
- React/RCTNetwork
- React/RCTNetwork (0.57.7):
- React/RCTNetwork (0.57.8):
- React/Core
- React/RCTText (0.57.7):
- React/RCTText (0.57.8):
- React/Core
- React/RCTWebSocket (0.57.7):
- React/RCTWebSocket (0.57.8):
- React/Core
- React/fishhook
- React/RCTBlob
@ -69,11 +69,11 @@ PODS:
- React/Core
- RSKImageCropper
- RSKImageCropper (2.2.1)
- SDWebImage/Core (4.4.2)
- SDWebImage/GIF (4.4.2):
- SDWebImage/Core (4.4.3)
- SDWebImage/GIF (4.4.3):
- FLAnimatedImage (~> 1.0)
- SDWebImage/Core
- yoga (0.57.7.React)
- yoga (0.57.8.React)
DEPENDENCIES:
- AppCenter/Analytics (~> 1.11.0)
@ -136,7 +136,7 @@ SPEC CHECKSUMS:
react-native-fast-image: cba3d9bf9c2cf8ddb643d887a686c53a5dd90a2c
RNImageCropPicker: 32ca4b9fef4e1b7b85ba69494242122948117e06
RSKImageCropper: 98296ad26b41753f796b6898d015509598f13d97
SDWebImage: 624d6e296c69b244bcede364c72ae0430ac14681
SDWebImage: c5594f1a19c48d526d321e548902b56b479cd508
yoga: b1ce48b6cf950b98deae82838f5173ea7cf89e85
PODFILE CHECKSUM: eb441adf4e362d192a91bff81223b7c865b15678

View File

@ -1,6 +1,6 @@
{
"name": "React",
"version": "0.57.7",
"version": "0.57.8",
"summary": "A framework for building native apps using React",
"description": "React Native apps are built using the React JS\nframework, and render directly to native UIKit\nelements using a fully asynchronous architecture.\nThere is no browser and no HTML. We have picked what\nwe think is the best set of features from these and\nother technologies to build what we hope to become\nthe best product development framework available,\nwith an emphasis on iteration speed, developer\ndelight, continuity of technology, and absolutely\nbeautiful and fast products with no compromises in\nquality or capability.",
"homepage": "http://facebook.github.io/react-native/",
@ -8,7 +8,7 @@
"authors": "Facebook",
"source": {
"git": "https://github.com/facebook/react-native.git",
"tag": "v0.57.7"
"tag": "v0.57.8"
},
"default_subspecs": "Core",
"requires_arc": true,
@ -30,7 +30,7 @@
"name": "Core",
"dependencies": {
"yoga": [
"0.57.7.React"
"0.57.8.React"
]
},
"source_files": "React/**/*.{c,h,m,mm,S,cpp}",

View File

@ -1,6 +1,6 @@
{
"name": "yoga",
"version": "0.57.7.React",
"version": "0.57.8.React",
"license": {
"type": "MIT"
},
@ -11,7 +11,7 @@
"authors": "Facebook",
"source": {
"git": "https://github.com/facebook/react-native.git",
"tag": "v0.57.7"
"tag": "v0.57.8"
},
"module_name": "yoga",
"requires_arc": false,

46
ios/Pods/Manifest.lock generated
View File

@ -17,50 +17,50 @@ PODS:
- glog
- glog (0.3.5)
- QBImagePickerController (3.4.0)
- React (0.57.7):
- React/Core (= 0.57.7)
- React (0.57.8):
- React/Core (= 0.57.8)
- react-native-fast-image (4.0.14):
- FLAnimatedImage
- React
- SDWebImage/Core
- SDWebImage/GIF
- React/Core (0.57.7):
- yoga (= 0.57.7.React)
- React/CxxBridge (0.57.7):
- React/Core (0.57.8):
- yoga (= 0.57.8.React)
- React/CxxBridge (0.57.8):
- Folly (= 2016.10.31.00)
- React/Core
- React/cxxreact
- React/cxxreact (0.57.7):
- React/cxxreact (0.57.8):
- boost-for-react-native (= 1.63.0)
- Folly (= 2016.10.31.00)
- React/jschelpers
- React/jsinspector
- React/DevSupport (0.57.7):
- React/DevSupport (0.57.8):
- React/Core
- React/RCTWebSocket
- React/fishhook (0.57.7)
- React/jschelpers (0.57.7):
- React/fishhook (0.57.8)
- React/jschelpers (0.57.8):
- Folly (= 2016.10.31.00)
- React/PrivateDatabase
- React/jsinspector (0.57.7)
- React/PrivateDatabase (0.57.7)
- React/RCTActionSheet (0.57.7):
- React/jsinspector (0.57.8)
- React/PrivateDatabase (0.57.8)
- React/RCTActionSheet (0.57.8):
- React/Core
- React/RCTAnimation (0.57.7):
- React/RCTAnimation (0.57.8):
- React/Core
- React/RCTBlob (0.57.7):
- React/RCTBlob (0.57.8):
- React/Core
- React/RCTCameraRoll (0.57.7):
- React/RCTCameraRoll (0.57.8):
- React/Core
- React/RCTImage
- React/RCTImage (0.57.7):
- React/RCTImage (0.57.8):
- React/Core
- React/RCTNetwork
- React/RCTNetwork (0.57.7):
- React/RCTNetwork (0.57.8):
- React/Core
- React/RCTText (0.57.7):
- React/RCTText (0.57.8):
- React/Core
- React/RCTWebSocket (0.57.7):
- React/RCTWebSocket (0.57.8):
- React/Core
- React/fishhook
- React/RCTBlob
@ -69,11 +69,11 @@ PODS:
- React/Core
- RSKImageCropper
- RSKImageCropper (2.2.1)
- SDWebImage/Core (4.4.2)
- SDWebImage/GIF (4.4.2):
- SDWebImage/Core (4.4.3)
- SDWebImage/GIF (4.4.3):
- FLAnimatedImage (~> 1.0)
- SDWebImage/Core
- yoga (0.57.7.React)
- yoga (0.57.8.React)
DEPENDENCIES:
- AppCenter/Analytics (~> 1.11.0)
@ -136,7 +136,7 @@ SPEC CHECKSUMS:
react-native-fast-image: cba3d9bf9c2cf8ddb643d887a686c53a5dd90a2c
RNImageCropPicker: 32ca4b9fef4e1b7b85ba69494242122948117e06
RSKImageCropper: 98296ad26b41753f796b6898d015509598f13d97
SDWebImage: 624d6e296c69b244bcede364c72ae0430ac14681
SDWebImage: c5594f1a19c48d526d321e548902b56b479cd508
yoga: b1ce48b6cf950b98deae82838f5173ea7cf89e85
PODFILE CHECKSUM: eb441adf4e362d192a91bff81223b7c865b15678

View File

@ -1,16 +1,14 @@
<p align="center" >
<p align="center">
<img src="SDWebImage_logo.png" title="SDWebImage logo" float=left>
</p>
[![Build Status](http://img.shields.io/travis/rs/SDWebImage/master.svg?style=flat)](https://travis-ci.org/rs/SDWebImage)
[![Build Status](http://img.shields.io/travis/SDWebImage/SDWebImage/master.svg?style=flat)](https://travis-ci.org/SDWebImage/SDWebImage)
[![Pod Version](http://img.shields.io/cocoapods/v/SDWebImage.svg?style=flat)](http://cocoadocs.org/docsets/SDWebImage/)
[![Pod Platform](http://img.shields.io/cocoapods/p/SDWebImage.svg?style=flat)](http://cocoadocs.org/docsets/SDWebImage/)
[![Pod License](http://img.shields.io/cocoapods/l/SDWebImage.svg?style=flat)](https://www.apache.org/licenses/LICENSE-2.0.html)
[![Dependency Status](https://www.versioneye.com/objective-c/sdwebimage/badge.svg?style=flat)](https://www.versioneye.com/objective-c/sdwebimage)
[![Reference Status](https://www.versioneye.com/objective-c/sdwebimage/reference_badge.svg?style=flat)](https://www.versioneye.com/objective-c/sdwebimage/references)
[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/rs/SDWebImage)
[![codecov](https://codecov.io/gh/rs/SDWebImage/branch/master/graph/badge.svg)](https://codecov.io/gh/rs/SDWebImage)
[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/SDWebImage/SDWebImage)
[![codecov](https://codecov.io/gh/SDWebImage/SDWebImage/branch/master/graph/badge.svg)](https://codecov.io/gh/SDWebImage/SDWebImage)
This library provides an async image downloader with cache support. For convenience, we added categories for UI elements like `UIImageView`, `UIButton`, `MKAnnotationView`.
@ -41,22 +39,22 @@ This library provides an async image downloader with cache support. For convenie
#### Backwards compatibility
- For iOS 5 and 6, use [any 3.x version up to 3.7.6](https://github.com/rs/SDWebImage/tree/3.7.6)
- For iOS < 5.0, please use the last [2.0 version](https://github.com/rs/SDWebImage/tree/2.0-compat).
- For iOS 5 and 6, use [any 3.x version up to 3.7.6](https://github.com/SDWebImage/SDWebImage/tree/3.7.6)
- For iOS < 5.0, please use the last [2.0 version](https://github.com/SDWebImage/SDWebImage/tree/2.0-compat).
## Getting Started
- Read this Readme doc
- Read the [How to use section](https://github.com/rs/SDWebImage#how-to-use)
- Read the [How to use section](https://github.com/SDWebImage/SDWebImage#how-to-use)
- Read the [Documentation @ CocoaDocs](http://cocoadocs.org/docsets/SDWebImage/)
- Try the example by downloading the project from Github or even easier using CocoaPods try `pod try SDWebImage`
- Read the [Installation Guide](https://github.com/rs/SDWebImage/wiki/Installation-Guide)
- Read the [Installation Guide](https://github.com/SDWebImage/SDWebImage/wiki/Installation-Guide)
- Read the [SDWebImage 4.0 Migration Guide](Docs/SDWebImage-4.0-Migration-guide.md) to get an idea of the changes from 3.x to 4.x
- Read the [Common Problems](https://github.com/rs/SDWebImage/wiki/Common-Problems) to find the solution for common problems
- Go to the [Wiki Page](https://github.com/rs/SDWebImage/wiki) for more information such as [Advanced Usage](https://github.com/rs/SDWebImage/wiki/Advanced-Usage)
- Read the [Common Problems](https://github.com/SDWebImage/SDWebImage/wiki/Common-Problems) to find the solution for common problems
- Go to the [Wiki Page](https://github.com/SDWebImage/SDWebImage/wiki) for more information such as [Advanced Usage](https://github.com/SDWebImage/SDWebImage/wiki/Advanced-Usage)
## Who Uses It
- Find out [who uses SDWebImage](https://github.com/rs/SDWebImage/wiki/Who-Uses-SDWebImage) and add your app to the list.
- Find out [who uses SDWebImage](https://github.com/SDWebImage/SDWebImage/wiki/Who-Uses-SDWebImage) and add your app to the list.
## Communication
@ -92,7 +90,7 @@ imageView.sd_setImage(with: URL(string: "http://www.domain.com/path/to/image.jpg
- Starting with the 4.0 version, we rely on [FLAnimatedImage](https://github.com/Flipboard/FLAnimatedImage) to take care of our animated images.
- If you use cocoapods, add `pod 'SDWebImage/GIF'` to your podfile.
- To use it, simply make sure you use `FLAnimatedImageView` instead of `UIImageView`.
- **Note**: there is a backwards compatible feature, so if you are still trying to load a GIF into a `UIImageView`, it will only show the 1st frame as a static image by default. However, you can enable the full GIF support by using the built-in GIF coder. See [GIF coder](https://github.com/rs/SDWebImage/wiki/Advanced-Usage#gif-coder)
- **Note**: there is a backwards compatible feature, so if you are still trying to load a GIF into a `UIImageView`, it will only show the 1st frame as a static image by default. However, you can enable the full GIF support by using the built-in GIF coder. See [GIF coder](https://github.com/SDWebImage/SDWebImage/wiki/Advanced-Usage#gif-coder)
- **Important**: FLAnimatedImage only works on the iOS platform. For macOS, use `NSImageView` with `animates` set to `YES` to show the entire animated images and `NO` to only show the 1st frame. For all the other platforms (tvOS, watchOS) we will fallback to the backwards compatibility feature described above
## Installation
@ -135,7 +133,7 @@ To install with carthage, follow the instruction on [Carthage](https://github.co
#### Cartfile
```
github "rs/SDWebImage"
github "SDWebImage/SDWebImage"
```
### Installation by cloning the repository
@ -166,14 +164,14 @@ community can help you solve it.
## Licenses
All source code is licensed under the [MIT License](https://raw.github.com/rs/SDWebImage/master/LICENSE).
All source code is licensed under the [MIT License](https://raw.github.com/SDWebImage/SDWebImage/master/LICENSE).
## Architecture
<p align="center" >
<p align="center">
<img src="Docs/SDWebImageClassDiagram.png" title="SDWebImage class diagram">
</p>
<p align="center" >
<p align="center">
<img src="Docs/SDWebImageSequenceDiagram.png" title="SDWebImage sequence diagram">
</p>

View File

@ -22,7 +22,7 @@ static inline FLAnimatedImage * SDWebImageCreateFLAnimatedImage(FLAnimatedImageV
}
FLAnimatedImage *animatedImage;
// Compatibility in 4.x for lower version FLAnimatedImage.
if ([FLAnimatedImage respondsToSelector:@selector(initWithAnimatedGIFData:optimalFrameCacheSize:predrawingEnabled:)]) {
if ([FLAnimatedImage instancesRespondToSelector:@selector(initWithAnimatedGIFData:optimalFrameCacheSize:predrawingEnabled:)]) {
animatedImage = [[FLAnimatedImage alloc] initWithAnimatedGIFData:imageData optimalFrameCacheSize:imageView.sd_optimalFrameCacheSize predrawingEnabled:imageView.sd_predrawingEnabled];
} else {
animatedImage = [[FLAnimatedImage alloc] initWithAnimatedGIFData:imageData];
@ -113,6 +113,7 @@ static inline FLAnimatedImage * SDWebImageCreateFLAnimatedImage(FLAnimatedImageV
options:(SDWebImageOptions)options
progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
completed:(nullable SDExternalCompletionBlock)completedBlock {
dispatch_group_t group = dispatch_group_create();
__weak typeof(self)weakSelf = self;
[self sd_internalSetImageWithURL:url
placeholderImage:placeholder
@ -121,44 +122,63 @@ static inline FLAnimatedImage * SDWebImageCreateFLAnimatedImage(FLAnimatedImageV
setImageBlock:^(UIImage *image, NSData *imageData) {
__strong typeof(weakSelf)strongSelf = weakSelf;
if (!strongSelf) {
dispatch_group_leave(group);
return;
}
// Step 1. Check memory cache (associate object)
FLAnimatedImage *associatedAnimatedImage = image.sd_FLAnimatedImage;
if (associatedAnimatedImage) {
// Asscociated animated image exist
// FLAnimatedImage framework contains a bug that cause GIF been rotated if previous rendered image orientation is not Up. We have to call `setImage:` with non-nil image to reset the state. See `https://github.com/SDWebImage/SDWebImage/issues/2402`
strongSelf.image = associatedAnimatedImage.posterImage;
strongSelf.animatedImage = associatedAnimatedImage;
strongSelf.image = nil;
dispatch_group_leave(group);
return;
}
// Step 2. Check if original compressed image data is "GIF"
BOOL isGIF = (image.sd_imageFormat == SDImageFormatGIF || [NSData sd_imageFormatForImageData:imageData] == SDImageFormatGIF);
if (!isGIF) {
// Check if placeholder, which does not trigger a backup disk cache query
BOOL isPlaceholder = (image == placeholder);
if (!isGIF || isPlaceholder) {
strongSelf.image = image;
strongSelf.animatedImage = nil;
dispatch_group_leave(group);
return;
}
// Step 3. Check if data exist or query disk cache
if (!imageData) {
NSString *key = [[SDWebImageManager sharedManager] cacheKeyForURL:url];
imageData = [[SDImageCache sharedImageCache] diskImageDataForKey:key];
}
// Step 4. Create FLAnimatedImage
FLAnimatedImage *animatedImage = SDWebImageCreateFLAnimatedImage(strongSelf, imageData);
// Step 5. Set animatedImage or normal image
if (animatedImage) {
if (strongSelf.sd_cacheFLAnimatedImage) {
image.sd_FLAnimatedImage = animatedImage;
__weak typeof(strongSelf) wweakSelf = strongSelf;
// Hack, mark we need should use dispatch group notify for completedBlock
objc_setAssociatedObject(group, &SDWebImageInternalSetImageGroupKey, @(YES), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
__strong typeof(wweakSelf) sstrongSelf = wweakSelf;
if (!sstrongSelf || ![url isEqual:sstrongSelf.sd_imageURL]) { return ; }
// Step 3. Check if data exist or query disk cache
__block NSData *gifData = imageData;
if (!gifData) {
NSString *key = [[SDWebImageManager sharedManager] cacheKeyForURL:url];
gifData = [[SDImageCache sharedImageCache] diskImageDataForKey:key];
}
strongSelf.animatedImage = animatedImage;
strongSelf.image = nil;
} else {
strongSelf.animatedImage = nil;
strongSelf.image = image;
}
// Step 4. Create FLAnimatedImage
FLAnimatedImage *animatedImage = SDWebImageCreateFLAnimatedImage(sstrongSelf, gifData);
dispatch_async(dispatch_get_main_queue(), ^{
if (![url isEqual:sstrongSelf.sd_imageURL]) { return ; }
// Step 5. Set animatedImage or normal image
if (animatedImage) {
if (sstrongSelf.sd_cacheFLAnimatedImage) {
image.sd_FLAnimatedImage = animatedImage;
}
sstrongSelf.image = animatedImage.posterImage;
sstrongSelf.animatedImage = animatedImage;
} else {
sstrongSelf.image = image;
sstrongSelf.animatedImage = nil;
}
dispatch_group_leave(group);
});
});
}
progress:progressBlock
completed:completedBlock];
completed:completedBlock
context:@{SDWebImageInternalSetImageGroupKey: group}];
}
@end

View File

@ -17,7 +17,8 @@ typedef NS_ENUM(NSInteger, SDImageFormat) {
SDImageFormatGIF,
SDImageFormatTIFF,
SDImageFormatWebP,
SDImageFormatHEIC
SDImageFormatHEIC,
SDImageFormatHEIF
};
@interface NSData (ImageContentType)

View File

@ -16,8 +16,9 @@
// 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
// AVFileTypeHEIC/AVFileTypeHEIF is defined in AVFoundation via iOS 11, we use this without import AVFoundation
#define kSDUTTypeHEIC ((__bridge CFStringRef)@"public.heic")
#define kSDUTTypeHEIF ((__bridge CFStringRef)@"public.heif")
@implementation NSData (ImageContentType)
@ -59,6 +60,9 @@
|| [testString isEqualToString:@"ftyphevx"]) {
return SDImageFormatHEIC;
}
if ([testString isEqualToString:@"ftypmif1"] || [testString isEqualToString:@"ftypmsf1"]) {
return SDImageFormatHEIF;
}
}
break;
}
@ -87,6 +91,9 @@
case SDImageFormatHEIC:
UTType = kSDUTTypeHEIC;
break;
case SDImageFormatHEIF:
UTType = kSDUTTypeHEIF;
break;
default:
// default is kUTTypePNG
UTType = kUTTypePNG;
@ -112,6 +119,8 @@
imageFormat = SDImageFormatWebP;
} else if (CFStringCompare(uttype, kSDUTTypeHEIC, 0) == kCFCompareEqualTo) {
imageFormat = SDImageFormatHEIC;
} else if (CFStringCompare(uttype, kSDUTTypeHEIF, 0) == kCFCompareEqualTo) {
imageFormat = SDImageFormatHEIF;
} else {
imageFormat = SDImageFormatUndefined;
}

View File

@ -11,6 +11,8 @@
#import "NSImage+WebCache.h"
#import "SDWebImageCodersManager.h"
#define SD_MAX_FILE_EXTENSION_LENGTH (NAME_MAX - CC_MD5_DIGEST_LENGTH * 2 - 1)
#define LOCK(lock) dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER);
#define UNLOCK(lock) dispatch_semaphore_signal(lock);
@ -253,6 +255,10 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
CC_MD5(str, (CC_LONG)strlen(str), r);
NSURL *keyURL = [NSURL URLWithString:key];
NSString *ext = keyURL ? keyURL.pathExtension : key.pathExtension;
// File system has file name length limit, we need to check if ext is too long, we don't add it to the filename
if (ext.length > SD_MAX_FILE_EXTENSION_LENGTH) {
ext = nil;
}
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], ext.length == 0 ? @"" : [NSString stringWithFormat:@".%@", ext]];
@ -390,7 +396,7 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
}
BOOL exists = [self.fileManager fileExistsAtPath:[self defaultCachePathForKey:key]];
// fallback because of https://github.com/rs/SDWebImage/pull/976 that added the extension to the disk file name
// fallback because of https://github.com/SDWebImage/SDWebImage/pull/976 that added the extension to the disk file name
// checking the key with and without the extension
if (!exists) {
exists = [self.fileManager fileExistsAtPath:[self defaultCachePathForKey:key].stringByDeletingPathExtension];
@ -444,7 +450,7 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
return data;
}
// fallback because of https://github.com/rs/SDWebImage/pull/976 that added the extension to the disk file name
// fallback because of https://github.com/SDWebImage/SDWebImage/pull/976 that added the extension to the disk file name
// checking the key with and without the extension
data = [NSData dataWithContentsOfFile:defaultPath.stringByDeletingPathExtension options:self.config.diskCacheReadingOptions error:nil];
if (data) {
@ -459,7 +465,7 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
return imageData;
}
// fallback because of https://github.com/rs/SDWebImage/pull/976 that added the extension to the disk file name
// fallback because of https://github.com/SDWebImage/SDWebImage/pull/976 that added the extension to the disk file name
// checking the key with and without the extension
imageData = [NSData dataWithContentsOfFile:filePath.stringByDeletingPathExtension options:self.config.diskCacheReadingOptions error:nil];
if (imageData) {
@ -529,12 +535,13 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
@autoreleasepool {
NSData *diskData = [self diskImageDataBySearchingAllPathsForKey:key];
UIImage *diskImage;
SDImageCacheType cacheType = SDImageCacheTypeDisk;
SDImageCacheType cacheType = SDImageCacheTypeNone;
if (image) {
// the image is from in-memory cache
diskImage = image;
cacheType = SDImageCacheTypeMemory;
} else if (diskData) {
cacheType = SDImageCacheTypeDisk;
// decode image data only if in-memory cache missed
diskImage = [self diskImageForKey:key data:diskData options:options];
if (diskImage && self.config.shouldCacheImagesInMemory) {
@ -707,10 +714,10 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
// Target half of our maximum cache size for this cleanup pass.
const NSUInteger desiredCacheSize = self.config.maxCacheSize / 2;
// Sort the remaining cache files by their last modification time (oldest first).
// Sort the remaining cache files by their last modification time or last access time (oldest first).
NSArray<NSURL *> *sortedFiles = [cacheFiles keysSortedByValueWithOptions:NSSortConcurrent
usingComparator:^NSComparisonResult(id obj1, id obj2) {
return [obj1[NSURLContentModificationDateKey] compare:obj2[NSURLContentModificationDateKey]];
return [obj1[cacheContentDateKey] compare:obj2[cacheContentDateKey]];
}];
// Delete files until we fall below our desired cache size.

View File

@ -56,10 +56,12 @@ inline UIImage *SDScaledImageForKey(NSString * _Nullable key, UIImage * _Nullabl
scale = 3.0;
}
}
UIImage *scaledImage = [[UIImage alloc] initWithCGImage:image.CGImage scale:scale orientation:image.imageOrientation];
scaledImage.sd_imageFormat = image.sd_imageFormat;
image = scaledImage;
if (scale != image.scale) {
UIImage *scaledImage = [[UIImage alloc] initWithCGImage:image.CGImage scale:scale orientation:image.imageOrientation];
scaledImage.sd_imageFormat = image.sd_imageFormat;
image = scaledImage;
}
}
return image;
}

View File

@ -197,12 +197,13 @@ typedef SDHTTPHeadersDictionary * _Nullable (^SDWebImageDownloaderHeadersFilterB
- (nullable NSString *)valueForHTTPHeaderField:(nullable NSString *)field;
/**
* Sets a subclass of `SDWebImageDownloaderOperation` as the default
* `NSOperation` to be used each time SDWebImage constructs a request
* Sets a subclass of `NSOperation` and conforms to `SDWebImageDownloaderOperationInterface`.
* Default is `SDWebImageDownloaderOperation`.
* Can be used each time SDWebImage constructs a request
* operation to download an image.
*
* @param operationClass The subclass of `SDWebImageDownloaderOperation` to set
* as default. Passing `nil` will revert to `SDWebImageDownloaderOperation`.
* @param operationClass The subclass of `NSOperation` and conforms to `SDWebImageDownloaderOperationInterface`.
* Default is `SDWebImageDownloaderOperation`, Passing `nil` will revert to `SDWebImageDownloaderOperation`.
*/
- (void)setOperationClass:(nullable Class)operationClass;

View File

@ -37,7 +37,7 @@
@property (strong, nonatomic, nonnull) NSOperationQueue *downloadQueue;
@property (weak, nonatomic, nullable) NSOperation *lastAddedOperation;
@property (assign, nonatomic, nullable) Class operationClass;
@property (strong, nonatomic, nonnull) NSMutableDictionary<NSURL *, SDWebImageDownloaderOperation *> *URLOperations;
@property (strong, nonatomic, nonnull) NSMutableDictionary<NSURL *, NSOperation<SDWebImageDownloaderOperationInterface> *> *URLOperations;
@property (strong, nonatomic, nullable) SDHTTPHeadersMutableDictionary *HTTPHeaders;
@property (strong, nonatomic, nonnull) dispatch_semaphore_t operationsLock; // a lock to keep the access to `URLOperations` thread-safe
@property (strong, nonatomic, nonnull) dispatch_semaphore_t headersLock; // a lock to keep the access to `HTTPHeaders` thread-safe
@ -94,11 +94,32 @@
_downloadQueue.maxConcurrentOperationCount = 6;
_downloadQueue.name = @"com.hackemist.SDWebImageDownloader";
_URLOperations = [NSMutableDictionary new];
#ifdef SD_WEBP
_HTTPHeaders = [@{@"Accept": @"image/webp,image/*;q=0.8"} mutableCopy];
#else
_HTTPHeaders = [@{@"Accept": @"image/*;q=0.8"} mutableCopy];
SDHTTPHeadersMutableDictionary *headerDictionary = [SDHTTPHeadersMutableDictionary dictionary];
NSString *userAgent = nil;
#if SD_UIKIT
// User-Agent Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.43
userAgent = [NSString stringWithFormat:@"%@/%@ (%@; iOS %@; Scale/%0.2f)", [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleExecutableKey] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleIdentifierKey], [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleVersionKey], [[UIDevice currentDevice] model], [[UIDevice currentDevice] systemVersion], [[UIScreen mainScreen] scale]];
#elif SD_WATCH
// User-Agent Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.43
userAgent = [NSString stringWithFormat:@"%@/%@ (%@; watchOS %@; Scale/%0.2f)", [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleExecutableKey] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleIdentifierKey], [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleVersionKey], [[WKInterfaceDevice currentDevice] model], [[WKInterfaceDevice currentDevice] systemVersion], [[WKInterfaceDevice currentDevice] screenScale]];
#elif SD_MAC
userAgent = [NSString stringWithFormat:@"%@/%@ (Mac OS X %@)", [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleExecutableKey] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleIdentifierKey], [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleVersionKey], [[NSProcessInfo processInfo] operatingSystemVersionString]];
#endif
if (userAgent) {
if (![userAgent canBeConvertedToEncoding:NSASCIIStringEncoding]) {
NSMutableString *mutableUserAgent = [userAgent mutableCopy];
if (CFStringTransform((__bridge CFMutableStringRef)(mutableUserAgent), NULL, (__bridge CFStringRef)@"Any-Latin; Latin-ASCII; [:^ASCII:] Remove", false)) {
userAgent = mutableUserAgent;
}
}
headerDictionary[@"User-Agent"] = userAgent;
}
#ifdef SD_WEBP
headerDictionary[@"Accept"] = @"image/webp,image/*;q=0.8";
#else
headerDictionary[@"Accept"] = @"image/*;q=0.8";
#endif
_HTTPHeaders = headerDictionary;
_operationsLock = dispatch_semaphore_create(1);
_headersLock = dispatch_semaphore_create(1);
_downloadTimeout = 15.0;
@ -193,56 +214,49 @@
}
}
- (nullable SDWebImageDownloadToken *)downloadImageWithURL:(nullable NSURL *)url
options:(SDWebImageDownloaderOptions)options
progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
completed:(nullable SDWebImageDownloaderCompletedBlock)completedBlock {
__weak SDWebImageDownloader *wself = self;
- (NSOperation<SDWebImageDownloaderOperationInterface> *)createDownloaderOperationWithUrl:(nullable NSURL *)url
options:(SDWebImageDownloaderOptions)options {
NSTimeInterval timeoutInterval = self.downloadTimeout;
if (timeoutInterval == 0.0) {
timeoutInterval = 15.0;
}
return [self addProgressCallback:progressBlock completedBlock:completedBlock forURL:url createCallback:^SDWebImageDownloaderOperation *{
__strong __typeof (wself) sself = wself;
NSTimeInterval timeoutInterval = sself.downloadTimeout;
if (timeoutInterval == 0.0) {
timeoutInterval = 15.0;
}
// In order to prevent from potential duplicate caching (NSURLCache + SDImageCache) we disable the cache for image requests if told otherwise
NSURLRequestCachePolicy cachePolicy = options & SDWebImageDownloaderUseNSURLCache ? NSURLRequestUseProtocolCachePolicy : NSURLRequestReloadIgnoringLocalCacheData;
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url
cachePolicy:cachePolicy
timeoutInterval:timeoutInterval];
request.HTTPShouldHandleCookies = (options & SDWebImageDownloaderHandleCookies);
request.HTTPShouldUsePipelining = YES;
if (self.headersFilter) {
request.allHTTPHeaderFields = self.headersFilter(url, [self allHTTPHeaderFields]);
}
else {
request.allHTTPHeaderFields = [self allHTTPHeaderFields];
}
NSOperation<SDWebImageDownloaderOperationInterface> *operation = [[self.operationClass alloc] initWithRequest:request inSession:self.session options:options];
operation.shouldDecompressImages = self.shouldDecompressImages;
if (self.urlCredential) {
operation.credential = self.urlCredential;
} else if (self.username && self.password) {
operation.credential = [NSURLCredential credentialWithUser:self.username password:self.password persistence:NSURLCredentialPersistenceForSession];
}
if (options & SDWebImageDownloaderHighPriority) {
operation.queuePriority = NSOperationQueuePriorityHigh;
} else if (options & SDWebImageDownloaderLowPriority) {
operation.queuePriority = NSOperationQueuePriorityLow;
}
if (self.executionOrder == SDWebImageDownloaderLIFOExecutionOrder) {
// Emulate LIFO execution order by systematically adding new operations as last operation's dependency
[self.lastAddedOperation addDependency:operation];
self.lastAddedOperation = operation;
}
// In order to prevent from potential duplicate caching (NSURLCache + SDImageCache) we disable the cache for image requests if told otherwise
NSURLRequestCachePolicy cachePolicy = options & SDWebImageDownloaderUseNSURLCache ? NSURLRequestUseProtocolCachePolicy : NSURLRequestReloadIgnoringLocalCacheData;
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url
cachePolicy:cachePolicy
timeoutInterval:timeoutInterval];
request.HTTPShouldHandleCookies = (options & SDWebImageDownloaderHandleCookies);
request.HTTPShouldUsePipelining = YES;
if (sself.headersFilter) {
request.allHTTPHeaderFields = sself.headersFilter(url, [sself allHTTPHeaderFields]);
}
else {
request.allHTTPHeaderFields = [sself allHTTPHeaderFields];
}
SDWebImageDownloaderOperation *operation = [[sself.operationClass alloc] initWithRequest:request inSession:sself.session options:options];
operation.shouldDecompressImages = sself.shouldDecompressImages;
if (sself.urlCredential) {
operation.credential = sself.urlCredential;
} else if (sself.username && sself.password) {
operation.credential = [NSURLCredential credentialWithUser:sself.username password:sself.password persistence:NSURLCredentialPersistenceForSession];
}
if (options & SDWebImageDownloaderHighPriority) {
operation.queuePriority = NSOperationQueuePriorityHigh;
} else if (options & SDWebImageDownloaderLowPriority) {
operation.queuePriority = NSOperationQueuePriorityLow;
}
if (sself.executionOrder == SDWebImageDownloaderLIFOExecutionOrder) {
// Emulate LIFO execution order by systematically adding new operations as last operation's dependency
[sself.lastAddedOperation addDependency:operation];
sself.lastAddedOperation = operation;
}
return operation;
}];
return operation;
}
- (void)cancel:(nullable SDWebImageDownloadToken *)token {
@ -251,7 +265,7 @@
return;
}
LOCK(self.operationsLock);
SDWebImageDownloaderOperation *operation = [self.URLOperations objectForKey:url];
NSOperation<SDWebImageDownloaderOperationInterface> *operation = [self.URLOperations objectForKey:url];
if (operation) {
BOOL canceled = [operation cancel:token.downloadOperationCancelToken];
if (canceled) {
@ -261,10 +275,10 @@
UNLOCK(self.operationsLock);
}
- (nullable SDWebImageDownloadToken *)addProgressCallback:(SDWebImageDownloaderProgressBlock)progressBlock
completedBlock:(SDWebImageDownloaderCompletedBlock)completedBlock
forURL:(nullable NSURL *)url
createCallback:(SDWebImageDownloaderOperation *(^)(void))createCallback {
- (nullable SDWebImageDownloadToken *)downloadImageWithURL:(nullable NSURL *)url
options:(SDWebImageDownloaderOptions)options
progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
completed:(nullable SDWebImageDownloaderCompletedBlock)completedBlock {
// The URL will be used as the key to the callbacks dictionary so it cannot be nil. If it is nil immediately call the completed block with no image or data.
if (url == nil) {
if (completedBlock != nil) {
@ -274,10 +288,10 @@
}
LOCK(self.operationsLock);
SDWebImageDownloaderOperation *operation = [self.URLOperations objectForKey:url];
NSOperation<SDWebImageDownloaderOperationInterface> *operation = [self.URLOperations objectForKey:url];
// There is a case that the operation may be marked as finished, but not been removed from `self.URLOperations`.
if (!operation || operation.isFinished) {
operation = createCallback();
operation = [self createDownloaderOperationWithUrl:url options:options];
__weak typeof(self) wself = self;
operation.completionBlock = ^{
__strong typeof(wself) sself = wself;
@ -315,12 +329,14 @@
#pragma mark Helper methods
- (SDWebImageDownloaderOperation *)operationWithTask:(NSURLSessionTask *)task {
SDWebImageDownloaderOperation *returnOperation = nil;
for (SDWebImageDownloaderOperation *operation in self.downloadQueue.operations) {
if (operation.dataTask.taskIdentifier == task.taskIdentifier) {
returnOperation = operation;
break;
- (NSOperation<SDWebImageDownloaderOperationInterface> *)operationWithTask:(NSURLSessionTask *)task {
NSOperation<SDWebImageDownloaderOperationInterface> *returnOperation = nil;
for (NSOperation<SDWebImageDownloaderOperationInterface> *operation in self.downloadQueue.operations) {
if ([operation respondsToSelector:@selector(dataTask)]) {
if (operation.dataTask.taskIdentifier == task.taskIdentifier) {
returnOperation = operation;
break;
}
}
}
return returnOperation;
@ -334,7 +350,7 @@ didReceiveResponse:(NSURLResponse *)response
completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler {
// Identify the operation that runs this task and pass it the delegate method
SDWebImageDownloaderOperation *dataOperation = [self operationWithTask:dataTask];
NSOperation<SDWebImageDownloaderOperationInterface> *dataOperation = [self operationWithTask:dataTask];
if ([dataOperation respondsToSelector:@selector(URLSession:dataTask:didReceiveResponse:completionHandler:)]) {
[dataOperation URLSession:session dataTask:dataTask didReceiveResponse:response completionHandler:completionHandler];
} else {
@ -347,7 +363,7 @@ didReceiveResponse:(NSURLResponse *)response
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {
// Identify the operation that runs this task and pass it the delegate method
SDWebImageDownloaderOperation *dataOperation = [self operationWithTask:dataTask];
NSOperation<SDWebImageDownloaderOperationInterface> *dataOperation = [self operationWithTask:dataTask];
if ([dataOperation respondsToSelector:@selector(URLSession:dataTask:didReceiveData:)]) {
[dataOperation URLSession:session dataTask:dataTask didReceiveData:data];
}
@ -359,7 +375,7 @@ didReceiveResponse:(NSURLResponse *)response
completionHandler:(void (^)(NSCachedURLResponse *cachedResponse))completionHandler {
// Identify the operation that runs this task and pass it the delegate method
SDWebImageDownloaderOperation *dataOperation = [self operationWithTask:dataTask];
NSOperation<SDWebImageDownloaderOperationInterface> *dataOperation = [self operationWithTask:dataTask];
if ([dataOperation respondsToSelector:@selector(URLSession:dataTask:willCacheResponse:completionHandler:)]) {
[dataOperation URLSession:session dataTask:dataTask willCacheResponse:proposedResponse completionHandler:completionHandler];
} else {
@ -374,7 +390,7 @@ didReceiveResponse:(NSURLResponse *)response
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
// Identify the operation that runs this task and pass it the delegate method
SDWebImageDownloaderOperation *dataOperation = [self operationWithTask:task];
NSOperation<SDWebImageDownloaderOperationInterface> *dataOperation = [self operationWithTask:task];
if ([dataOperation respondsToSelector:@selector(URLSession:task:didCompleteWithError:)]) {
[dataOperation URLSession:session task:task didCompleteWithError:error];
}
@ -383,7 +399,7 @@ didReceiveResponse:(NSURLResponse *)response
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task willPerformHTTPRedirection:(NSHTTPURLResponse *)response newRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURLRequest * _Nullable))completionHandler {
// Identify the operation that runs this task and pass it the delegate method
SDWebImageDownloaderOperation *dataOperation = [self operationWithTask:task];
NSOperation<SDWebImageDownloaderOperationInterface> *dataOperation = [self operationWithTask:task];
if ([dataOperation respondsToSelector:@selector(URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler:)]) {
[dataOperation URLSession:session task:task willPerformHTTPRedirection:response newRequest:request completionHandler:completionHandler];
} else {
@ -396,7 +412,7 @@ didReceiveResponse:(NSURLResponse *)response
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler {
// Identify the operation that runs this task and pass it the delegate method
SDWebImageDownloaderOperation *dataOperation = [self operationWithTask:task];
NSOperation<SDWebImageDownloaderOperationInterface> *dataOperation = [self operationWithTask:task];
if ([dataOperation respondsToSelector:@selector(URLSession:task:didReceiveChallenge:completionHandler:)]) {
[dataOperation URLSession:session task:task didReceiveChallenge:challenge completionHandler:completionHandler];
} else {

View File

@ -21,8 +21,8 @@ FOUNDATION_EXPORT NSString * _Nonnull const SDWebImageDownloadFinishNotification
Describes a downloader operation. If one wants to use a custom downloader op, it needs to inherit from `NSOperation` and conform to this protocol
For the description about these methods, see `SDWebImageDownloaderOperation`
*/
@protocol SDWebImageDownloaderOperationInterface<NSObject>
@protocol SDWebImageDownloaderOperationInterface <NSURLSessionTaskDelegate, NSURLSessionDataDelegate>
@required
- (nonnull instancetype)initWithRequest:(nullable NSURLRequest *)request
inSession:(nullable NSURLSession *)session
options:(SDWebImageDownloaderOptions)options;
@ -38,10 +38,13 @@ FOUNDATION_EXPORT NSString * _Nonnull const SDWebImageDownloadFinishNotification
- (BOOL)cancel:(nullable id)token;
@optional
- (nullable NSURLSessionTask *)dataTask;
@end
@interface SDWebImageDownloaderOperation : NSOperation <SDWebImageDownloaderOperationInterface, SDWebImageOperation, NSURLSessionTaskDelegate, NSURLSessionDataDelegate>
@interface SDWebImageDownloaderOperation : NSOperation <SDWebImageDownloaderOperationInterface, SDWebImageOperation>
/**
* The request used by the operation's task.

View File

@ -345,17 +345,19 @@ didReceiveResponse:(NSURLResponse *)response
// progressive decode the image in coder queue
dispatch_async(self.coderQueue, ^{
UIImage *image = [self.progressiveCoder incrementallyDecodedImageWithData:imageData finished:finished];
if (image) {
NSString *key = [[SDWebImageManager sharedManager] cacheKeyForURL:self.request.URL];
image = [self scaledImageForKey:key image:image];
if (self.shouldDecompressImages) {
image = [[SDWebImageCodersManager sharedInstance] decompressedImageWithImage:image data:&imageData options:@{SDWebImageCoderScaleDownLargeImagesKey: @(NO)}];
@autoreleasepool {
UIImage *image = [self.progressiveCoder incrementallyDecodedImageWithData:imageData finished:finished];
if (image) {
NSString *key = [[SDWebImageManager sharedManager] cacheKeyForURL:self.request.URL];
image = [self scaledImageForKey:key image:image];
if (self.shouldDecompressImages) {
image = [[SDWebImageCodersManager sharedInstance] decompressedImageWithImage:image data:&imageData options:@{SDWebImageCoderScaleDownLargeImagesKey: @(NO)}];
}
// We do not keep the progressive decoding image even when `finished`=YES. Because they are for view rendering but not take full function from downloader options. And some coders implementation may not keep consistent between progressive decoding and normal decoding.
[self callCompletionBlocksWithImage:image imageData:nil error:nil finished:NO];
}
// We do not keep the progressive decoding image even when `finished`=YES. Because they are for view rendering but not take full function from downloader options. And some coders implementation may not keep consistent between progressive decoding and normal decoding.
[self callCompletionBlocksWithImage:image imageData:nil error:nil finished:NO];
}
});
}
@ -416,36 +418,38 @@ didReceiveResponse:(NSURLResponse *)response
} else {
// decode the image in coder queue
dispatch_async(self.coderQueue, ^{
UIImage *image = [[SDWebImageCodersManager sharedInstance] decodedImageWithData:imageData];
NSString *key = [[SDWebImageManager sharedManager] cacheKeyForURL:self.request.URL];
image = [self scaledImageForKey:key image:image];
BOOL shouldDecode = YES;
// Do not force decoding animated GIFs and WebPs
if (image.images) {
shouldDecode = NO;
} else {
#ifdef SD_WEBP
SDImageFormat imageFormat = [NSData sd_imageFormatForImageData:imageData];
if (imageFormat == SDImageFormatWebP) {
@autoreleasepool {
UIImage *image = [[SDWebImageCodersManager sharedInstance] decodedImageWithData:imageData];
NSString *key = [[SDWebImageManager sharedManager] cacheKeyForURL:self.request.URL];
image = [self scaledImageForKey:key image:image];
BOOL shouldDecode = YES;
// Do not force decoding animated GIFs and WebPs
if (image.images) {
shouldDecode = NO;
}
} else {
#ifdef SD_WEBP
SDImageFormat imageFormat = [NSData sd_imageFormatForImageData:imageData];
if (imageFormat == SDImageFormatWebP) {
shouldDecode = NO;
}
#endif
}
if (shouldDecode) {
if (self.shouldDecompressImages) {
BOOL shouldScaleDown = self.options & SDWebImageDownloaderScaleDownLargeImages;
image = [[SDWebImageCodersManager sharedInstance] decompressedImageWithImage:image data:&imageData options:@{SDWebImageCoderScaleDownLargeImagesKey: @(shouldScaleDown)}];
}
if (shouldDecode) {
if (self.shouldDecompressImages) {
BOOL shouldScaleDown = self.options & SDWebImageDownloaderScaleDownLargeImages;
image = [[SDWebImageCodersManager sharedInstance] decompressedImageWithImage:image data:&imageData options:@{SDWebImageCoderScaleDownLargeImagesKey: @(shouldScaleDown)}];
}
}
CGSize imageSize = image.size;
if (imageSize.width == 0 || imageSize.height == 0) {
[self callCompletionBlocksWithError:[NSError errorWithDomain:SDWebImageErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey : @"Downloaded image has 0 pixels"}]];
} else {
[self callCompletionBlocksWithImage:image imageData:imageData error:nil finished:YES];
}
[self done];
}
CGSize imageSize = image.size;
if (imageSize.width == 0 || imageSize.height == 0) {
[self callCompletionBlocksWithError:[NSError errorWithDomain:SDWebImageErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey : @"Downloaded image has 0 pixels"}]];
} else {
[self callCompletionBlocksWithImage:image imageData:imageData error:nil finished:YES];
}
[self done];
});
}
} else {

View File

@ -74,6 +74,9 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over
case SDImageFormatHEIC:
// Check HEIC decoding compatibility
return [[self class] canDecodeFromHEICFormat];
case SDImageFormatHEIF:
// Check HEIF decoding compatibility
return [[self class] canDecodeFromHEIFFormat];
default:
return YES;
}
@ -87,6 +90,9 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over
case SDImageFormatHEIC:
// Check HEIC decoding compatibility
return [[self class] canDecodeFromHEICFormat];
case SDImageFormatHEIF:
// Check HEIF decoding compatibility
return [[self class] canDecodeFromHEIFFormat];
default:
return YES;
}
@ -372,6 +378,9 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over
case SDImageFormatHEIC:
// Check HEIC encoding compatibility
return [[self class] canEncodeToHEICFormat];
case SDImageFormatHEIF:
// Check HEIF encoding compatibility
return [[self class] canEncodeToHEIFFormat];
default:
return YES;
}
@ -440,28 +449,24 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over
static BOOL canDecode = NO;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunguarded-availability"
#if TARGET_OS_SIMULATOR || SD_WATCH
canDecode = NO;
#elif SD_MAC
NSProcessInfo *processInfo = [NSProcessInfo processInfo];
if ([processInfo respondsToSelector:@selector(operatingSystemVersion)]) {
// macOS 10.13+
canDecode = processInfo.operatingSystemVersion.minorVersion >= 13;
} else {
canDecode = NO;
CFStringRef imageUTType = [NSData sd_UTTypeFromSDImageFormat:SDImageFormatHEIC];
NSArray *imageUTTypes = (__bridge_transfer NSArray *)CGImageSourceCopyTypeIdentifiers();
if ([imageUTTypes containsObject:(__bridge NSString *)(imageUTType)]) {
canDecode = YES;
}
#elif SD_UIKIT
NSProcessInfo *processInfo = [NSProcessInfo processInfo];
if ([processInfo respondsToSelector:@selector(operatingSystemVersion)]) {
// iOS 11+ && tvOS 11+
canDecode = processInfo.operatingSystemVersion.majorVersion >= 11;
} else {
canDecode = NO;
});
return canDecode;
}
+ (BOOL)canDecodeFromHEIFFormat {
static BOOL canDecode = NO;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
CFStringRef imageUTType = [NSData sd_UTTypeFromSDImageFormat:SDImageFormatHEIF];
NSArray *imageUTTypes = (__bridge_transfer NSArray *)CGImageSourceCopyTypeIdentifiers();
if ([imageUTTypes containsObject:(__bridge NSString *)(imageUTType)]) {
canDecode = YES;
}
#endif
#pragma clang diagnostic pop
});
return canDecode;
}
@ -487,6 +492,27 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over
return canEncode;
}
+ (BOOL)canEncodeToHEIFFormat {
static BOOL canEncode = NO;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSMutableData *imageData = [NSMutableData data];
CFStringRef imageUTType = [NSData sd_UTTypeFromSDImageFormat:SDImageFormatHEIF];
// Create an image destination.
CGImageDestinationRef imageDestination = CGImageDestinationCreateWithData((__bridge CFMutableDataRef)imageData, imageUTType, 1, NULL);
if (!imageDestination) {
// Can't encode to HEIF
canEncode = NO;
} else {
// Can encode to HEIF
CFRelease(imageDestination);
canEncode = YES;
}
});
return canEncode;
}
#if SD_UIKIT || SD_WATCH
+ (BOOL)shouldScaleDownImage:(nonnull UIImage *)image {
BOOL shouldScaleDown = YES;

View File

@ -243,28 +243,32 @@
// Image refresh hit the NSURLCache cache, do not call the completion block
} else if (downloadedImage && (!downloadedImage.images || (options & SDWebImageTransformAnimatedImage)) && [self.delegate respondsToSelector:@selector(imageManager:transformDownloadedImage:withURL:)]) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
UIImage *transformedImage = [self.delegate imageManager:self transformDownloadedImage:downloadedImage withURL:url];
if (transformedImage && finished) {
BOOL imageWasTransformed = ![transformedImage isEqual:downloadedImage];
NSData *cacheData;
// pass nil if the image was transformed, so we can recalculate the data from the image
if (self.cacheSerializer) {
cacheData = self.cacheSerializer(transformedImage, (imageWasTransformed ? nil : downloadedData), url);
} else {
cacheData = (imageWasTransformed ? nil : downloadedData);
@autoreleasepool {
UIImage *transformedImage = [self.delegate imageManager:self transformDownloadedImage:downloadedImage withURL:url];
if (transformedImage && finished) {
BOOL imageWasTransformed = ![transformedImage isEqual:downloadedImage];
NSData *cacheData;
// pass nil if the image was transformed, so we can recalculate the data from the image
if (self.cacheSerializer) {
cacheData = self.cacheSerializer(transformedImage, (imageWasTransformed ? nil : downloadedData), url);
} else {
cacheData = (imageWasTransformed ? nil : downloadedData);
}
[self.imageCache storeImage:transformedImage imageData:cacheData forKey:key toDisk:cacheOnDisk completion:nil];
}
[self.imageCache storeImage:transformedImage imageData:cacheData forKey:key toDisk:cacheOnDisk completion:nil];
[self callCompletionBlockForOperation:strongSubOperation completion:completedBlock image:transformedImage data:downloadedData error:nil cacheType:SDImageCacheTypeNone finished:finished url:url];
}
[self callCompletionBlockForOperation:strongSubOperation completion:completedBlock image:transformedImage data:downloadedData error:nil cacheType:SDImageCacheTypeNone finished:finished url:url];
});
} else {
if (downloadedImage && finished) {
if (self.cacheSerializer) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
NSData *cacheData = self.cacheSerializer(downloadedImage, downloadedData, url);
[self.imageCache storeImage:downloadedImage imageData:cacheData forKey:key toDisk:cacheOnDisk completion:nil];
@autoreleasepool {
NSData *cacheData = self.cacheSerializer(downloadedImage, downloadedData, url);
[self.imageCache storeImage:downloadedImage imageData:cacheData forKey:key toDisk:cacheOnDisk completion:nil];
}
});
} else {
[self.imageCache storeImage:downloadedImage imageData:downloadedData forKey:key toDisk:cacheOnDisk completion:nil];

View File

@ -13,7 +13,7 @@
/**
A Dispatch group to maintain setImageBlock and completionBlock. This key should be used only internally and may be changed in the future. (dispatch_group_t)
*/
FOUNDATION_EXPORT NSString * _Nonnull const SDWebImageInternalSetImageGroupKey __deprecated_msg("Key Deprecated. Does nothing. This key should be used only internally");
FOUNDATION_EXPORT NSString * _Nonnull const SDWebImageInternalSetImageGroupKey;
/**
A SDWebImageManager instance to control the image download and cache process using in UIImageView+WebCache category and likes. If not provided, use the shared manager (SDWebImageManager)
*/

View File

@ -64,7 +64,11 @@ static char TAG_ACTIVITY_SHOW;
[self sd_cancelImageLoadOperationWithKey:validOperationKey];
objc_setAssociatedObject(self, &imageURLKey, url, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
dispatch_group_t group = context[SDWebImageInternalSetImageGroupKey];
if (!(options & SDWebImageDelayPlaceholder)) {
if (group) {
dispatch_group_enter(group);
}
dispatch_main_async_safe(^{
[self sd_setImage:placeholder imageData:nil basedOnClassOrViaCustomSetImageBlock:setImageBlock];
});
@ -82,10 +86,8 @@ static char TAG_ACTIVITY_SHOW;
self.sd_imageProgress.totalUnitCount = 0;
self.sd_imageProgress.completedUnitCount = 0;
SDWebImageManager *manager;
if ([context valueForKey:SDWebImageExternalCustomManagerKey]) {
manager = (SDWebImageManager *)[context valueForKey:SDWebImageExternalCustomManagerKey];
} else {
SDWebImageManager *manager = [context objectForKey:SDWebImageExternalCustomManagerKey];
if (!manager) {
manager = [SDWebImageManager sharedManager];
}
@ -149,12 +151,25 @@ static char TAG_ACTIVITY_SHOW;
}
#endif
dispatch_main_async_safe(^{
if (group) {
dispatch_group_enter(group);
}
#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();
if (group) {
// compatible code for FLAnimatedImage, because we assume completedBlock called after image was set. This will be removed in 5.x
BOOL shouldUseGroup = [objc_getAssociatedObject(group, &SDWebImageInternalSetImageGroupKey) boolValue];
if (shouldUseGroup) {
dispatch_group_notify(group, dispatch_get_main_queue(), callCompletedBlockClojure);
} else {
callCompletedBlockClojure();
}
} else {
callCompletedBlockClojure();
}
});
}];
[self sd_setImageLoadOperation:operation forKey:validOperationKey];

View File

@ -5,7 +5,6 @@
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */; };
00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */; };

View File

@ -80,8 +80,6 @@
<array>
<string>remote-notification</string>
</array>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>