Merge branch 'master' of github.com:rs/SDWebImage
This commit is contained in:
commit
5fbbf73986
37
CHANGELOG.md
37
CHANGELOG.md
|
@ -1,3 +1,40 @@
|
|||
## [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)
|
||||
|
||||
#### Fixes
|
||||
|
||||
- Fix `SDWebImageDownloaderOperation` not call `done` when use `SDWebImageDownloaderIgnoreCachedResponse` #2049
|
||||
- Static `WebP` decoding little enhancement. Do not need create `WebP` iterator for static images #2050
|
||||
- Change `finished` check from `equal` to `equal or greater than` to protect accident condition #2051
|
||||
|
||||
## [4.1.1 - 4.1 patch, on Oct 6th, 2017](https://github.com/rs/SDWebImage/releases/tag/4.1.1)
|
||||
See [all tickets marked for the 4.1.1 release](https://github.com/rs/SDWebImage/milestone/14)
|
||||
|
||||
#### Fixes
|
||||
|
||||
- Fixed crash on `[SDWebImageDownloaderOperation reset]_block_invoke` 2f892f9 fixes #1883
|
||||
- Fixed `SDWebImageDownloadOperation` `imageData` multi-thread issue #2011 fixes #1998 `[SDWebImageDownloaderOperation URLSession:dataTask:didReceiveData:]` crash
|
||||
- Fixed `CFRelease` on `NULL` if `CGImageSourceRef` create failed #1978 fixes #1968 #1834 #1947
|
||||
- Fixed request cache policy #1994 #2032 fixes #1993 #1861 #1623 was introduced by #1737 (unit test #2031)
|
||||
- Fixed `CGBitmapContextCreate` bitmap memory leak #1976 replaces #1860 fixes #1974
|
||||
- Fixed issue #2001, add `sd_currentBackgroundImageURL` and `sd_backgroundImageURLForState:` for `UIButton` #2002
|
||||
- Set `UIButton` placeholer-image even if the url is `nil` #2043 fixes #1721 #1964 replaces #1790
|
||||
- Use `CGImageSourceCreateIncremental` to perform progressive decoding instead of decode partial data each time from the beginning to improve performance and remove that gray background #2040 fixes #1899
|
||||
- Fix *SDWebImage v4* can not import *libwebp* framework's header files #1983 fixes #1887
|
||||
- Fix unreachable code build warning on `macOS` #1984
|
||||
|
||||
#### Improvements
|
||||
|
||||
- Performance enhancement related to single `WebP` and animated `WebP` decoding #1985 fixes #1999 #1885
|
||||
- Use `FOUNDATION_EXPORT` over `extern` #1977
|
||||
- Move common test logic to `SDTestCase` #1980
|
||||
- Enabled `CLANG_WARN_STRICT_PROTOTYPES` #1995 #2027 fixes #2022
|
||||
- Update `macOS Demo` deployment target to `10.10` to support build on `Xcode 9` #2035
|
||||
|
||||
#### Docs
|
||||
|
||||
- Updated *Manual Installation* section #2030 fixes #2012
|
||||
|
||||
## [4.1.0 - Swift API cleanup, on Jul 31st, 2017](https://github.com/rs/SDWebImage/releases/tag/4.1.0)
|
||||
See [all tickets marked for the 4.1.0 release](https://github.com/rs/SDWebImage/milestone/13)
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ git clone --recursive https://github.com/rs/SDWebImage.git
|
|||
|
||||
Open the "Build Settings" tab, in the "Linking" section, locate the "Other Linker Flags" setting and add the "-ObjC" flag:
|
||||
|
||||
![Other Linker Flags](http://dl.dropbox.com/u/123346/SDWebImage/10_other_linker_flags.jpg)
|
||||
![Other Linker Flags](https://user-images.githubusercontent.com/6919743/30030628-be2daf6a-91c0-11e7-8b5c-e0ac92d16b80.png)
|
||||
|
||||
Alternatively, if this causes compilation problems with frameworks that extend optional libraries, such as Parse, RestKit or opencv2, instead of the -ObjC flag use:
|
||||
```
|
||||
|
@ -30,4 +30,4 @@ If you're using Cocoa Pods and have any frameworks that extend optional librarie
|
|||
and this:
|
||||
```
|
||||
$(inherited)
|
||||
```
|
||||
```
|
||||
|
|
|
@ -517,7 +517,7 @@
|
|||
5376128C155AB74D005750A4 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0710;
|
||||
LastUpgradeCheck = 0900;
|
||||
ORGANIZATIONNAME = Dailymotion;
|
||||
TargetAttributes = {
|
||||
4314D1A51D0E1181004B36C9 = {
|
||||
|
@ -887,7 +887,7 @@
|
|||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
INFOPLIST_FILE = "SDWebImage OSX Demo/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.8;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.10;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.dailymotion.SDWebImage-OSX-Demo";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
|
@ -927,7 +927,7 @@
|
|||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
INFOPLIST_FILE = "SDWebImage OSX Demo/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.8;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.10;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.dailymotion.SDWebImage-OSX-Demo";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
|
@ -1094,11 +1094,28 @@
|
|||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = "compiler-default";
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
|
@ -1106,8 +1123,11 @@
|
|||
);
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_VERSION = "";
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
};
|
||||
|
@ -1118,12 +1138,32 @@
|
|||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = YES;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = "compiler-default";
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_VERSION = "";
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0800"
|
||||
LastUpgradeVersion = "0900"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -26,6 +26,7 @@
|
|||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
|
@ -45,6 +46,7 @@
|
|||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0800"
|
||||
LastUpgradeVersion = "0900"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -26,6 +26,7 @@
|
|||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
|
@ -45,6 +46,7 @@
|
|||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0800"
|
||||
LastUpgradeVersion = "0900"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -54,6 +54,7 @@
|
|||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
|
@ -73,6 +74,7 @@
|
|||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
|
|
|
@ -43,11 +43,13 @@
|
|||
placeholderImage:nil
|
||||
options:SDWebImageProgressiveDownload
|
||||
progress:^(NSInteger receivedSize, NSInteger expectedSize, NSURL *targetURL) {
|
||||
if (!activityIndicator) {
|
||||
[weakImageView addSubview:activityIndicator = [UIActivityIndicatorView.alloc initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]];
|
||||
activityIndicator.center = weakImageView.center;
|
||||
[activityIndicator startAnimating];
|
||||
}
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (!activityIndicator) {
|
||||
[weakImageView addSubview:activityIndicator = [UIActivityIndicatorView.alloc initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]];
|
||||
activityIndicator.center = weakImageView.center;
|
||||
[activityIndicator startAnimating];
|
||||
}
|
||||
});
|
||||
}
|
||||
completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
|
||||
[activityIndicator removeFromSuperview];
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
Pod::Spec.new do |s|
|
||||
s.name = 'SDWebImage'
|
||||
s.version = '4.1.0'
|
||||
s.version = '4.1.2'
|
||||
|
||||
s.osx.deployment_target = '10.8'
|
||||
s.ios.deployment_target = '7.0'
|
||||
|
|
|
@ -2052,7 +2052,7 @@
|
|||
53922D66148C55810056699D /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0800;
|
||||
LastUpgradeCheck = 0900;
|
||||
ORGANIZATIONNAME = Dailymotion;
|
||||
TargetAttributes = {
|
||||
00733A4B1BC487C000A5A117 = {
|
||||
|
@ -3089,14 +3089,19 @@
|
|||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = NO;
|
||||
|
@ -3152,14 +3157,19 @@
|
|||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = NO;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0800"
|
||||
LastUpgradeVersion = "0900"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -26,6 +26,7 @@
|
|||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
|
@ -36,6 +37,7 @@
|
|||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0800"
|
||||
LastUpgradeVersion = "0900"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -26,6 +26,7 @@
|
|||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
|
@ -36,6 +37,7 @@
|
|||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0800"
|
||||
LastUpgradeVersion = "0900"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -26,6 +26,7 @@
|
|||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
|
@ -36,6 +37,7 @@
|
|||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0800"
|
||||
LastUpgradeVersion = "0900"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -26,6 +26,7 @@
|
|||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
|
@ -36,6 +37,7 @@
|
|||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0800"
|
||||
LastUpgradeVersion = "0900"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -26,6 +26,7 @@
|
|||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
|
@ -36,6 +37,7 @@
|
|||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0800"
|
||||
LastUpgradeVersion = "0900"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -26,6 +26,7 @@
|
|||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
|
@ -36,6 +37,7 @@
|
|||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0800"
|
||||
LastUpgradeVersion = "0900"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -26,6 +26,7 @@
|
|||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
|
@ -45,6 +46,7 @@
|
|||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
#if __has_include(<FLAnimatedImage/FLAnimatedImage.h>)
|
||||
#import <FLAnimatedImage/FLAnimatedImage.h>
|
||||
#else
|
||||
#import "FLAnimatedImageView.h"
|
||||
#import "FLAnimatedImage.h"
|
||||
#endif
|
||||
|
||||
#import "SDWebImageManager.h"
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#import "UIView+WebCacheOperation.h"
|
||||
#import "UIView+WebCache.h"
|
||||
#import "NSData+ImageContentType.h"
|
||||
#import "FLAnimatedImage.h"
|
||||
#import "UIImageView+WebCache.h"
|
||||
|
||||
@implementation FLAnimatedImageView (WebCache)
|
||||
|
|
|
@ -367,6 +367,12 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
|
|||
if (data) {
|
||||
UIImage *image = [UIImage sd_imageWithData:data];
|
||||
image = [self scaledImageForKey:key image:image];
|
||||
#ifdef SD_WEBP
|
||||
SDImageFormat imageFormat = [NSData sd_imageFormatForImageData:data];
|
||||
if (imageFormat == SDImageFormatWebP) {
|
||||
return image;
|
||||
}
|
||||
#endif
|
||||
if (self.config.shouldDecompressImages) {
|
||||
image = [UIImage decodedImageWithImage:image];
|
||||
}
|
||||
|
|
|
@ -23,7 +23,6 @@ typedef NS_OPTIONS(NSUInteger, SDWebImageDownloaderOptions) {
|
|||
/**
|
||||
* Call completion block with nil image/imageData if the image was read from NSURLCache
|
||||
* (to be combined with `SDWebImageDownloaderUseNSURLCache`).
|
||||
* I think this option should be renamed to 'SDWebImageDownloaderUsingCachedResponseDontLoad'
|
||||
*/
|
||||
SDWebImageDownloaderIgnoreCachedResponse = 1 << 3,
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
|
||||
#import "SDWebImageDownloader.h"
|
||||
#import "SDWebImageDownloaderOperation.h"
|
||||
#import <ImageIO/ImageIO.h>
|
||||
|
||||
@implementation SDWebImageDownloadToken
|
||||
@end
|
||||
|
@ -166,16 +165,10 @@
|
|||
}
|
||||
|
||||
// In order to prevent from potential duplicate caching (NSURLCache + SDImageCache) we disable the cache for image requests if told otherwise
|
||||
NSURLRequestCachePolicy cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
|
||||
if (options & SDWebImageDownloaderUseNSURLCache) {
|
||||
if (options & SDWebImageDownloaderIgnoreCachedResponse) {
|
||||
cachePolicy = NSURLRequestReturnCacheDataDontLoad;
|
||||
} else {
|
||||
cachePolicy = NSURLRequestUseProtocolCachePolicy;
|
||||
}
|
||||
}
|
||||
|
||||
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url cachePolicy:cachePolicy timeoutInterval:timeoutInterval];
|
||||
NSURLRequestCachePolicy cachePolicy = options & SDWebImageDownloaderUseNSURLCache ? NSURLRequestUseProtocolCachePolicy : NSURLRequestReloadIgnoringLocalCacheData;
|
||||
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url
|
||||
cachePolicy:cachePolicy
|
||||
timeoutInterval:timeoutInterval];
|
||||
|
||||
request.HTTPShouldHandleCookies = (options & SDWebImageDownloaderHandleCookies);
|
||||
request.HTTPShouldUsePipelining = YES;
|
||||
|
|
|
@ -30,6 +30,7 @@ typedef NSMutableDictionary<NSString *, id> SDCallbacksDictionary;
|
|||
@property (assign, nonatomic, getter = isExecuting) BOOL executing;
|
||||
@property (assign, nonatomic, getter = isFinished) BOOL finished;
|
||||
@property (strong, nonatomic, nullable) NSMutableData *imageData;
|
||||
@property (copy, nonatomic, nullable) NSData *cachedData;
|
||||
|
||||
// This is weak because it is injected by whoever manages this session. If this gets nil-ed out, we won't be able to run
|
||||
// the task associated with this operation
|
||||
|
@ -48,10 +49,11 @@ typedef NSMutableDictionary<NSString *, id> SDCallbacksDictionary;
|
|||
@end
|
||||
|
||||
@implementation SDWebImageDownloaderOperation {
|
||||
size_t width, height;
|
||||
size_t _width, _height;
|
||||
#if SD_UIKIT || SD_WATCH
|
||||
UIImageOrientation orientation;
|
||||
UIImageOrientation _orientation;
|
||||
#endif
|
||||
CGImageSourceRef _imageSource;
|
||||
}
|
||||
|
||||
@synthesize executing = _executing;
|
||||
|
@ -80,6 +82,10 @@ typedef NSMutableDictionary<NSString *, id> SDCallbacksDictionary;
|
|||
|
||||
- (void)dealloc {
|
||||
SDDispatchQueueRelease(_barrierQueue);
|
||||
if (_imageSource) {
|
||||
CFRelease(_imageSource);
|
||||
_imageSource = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
- (nullable id)addHandlersForProgress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
|
||||
|
@ -143,6 +149,14 @@ typedef NSMutableDictionary<NSString *, id> SDCallbacksDictionary;
|
|||
}];
|
||||
}
|
||||
#endif
|
||||
if (self.options & SDWebImageDownloaderIgnoreCachedResponse) {
|
||||
// Grab the cached data for later check
|
||||
NSCachedURLResponse *cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:self.request];
|
||||
if (cachedResponse) {
|
||||
self.cachedData = cachedResponse.data;
|
||||
}
|
||||
}
|
||||
|
||||
NSURLSession *session = self.unownedSession;
|
||||
if (!self.unownedSession) {
|
||||
NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
|
||||
|
@ -228,7 +242,20 @@ typedef NSMutableDictionary<NSString *, id> SDCallbacksDictionary;
|
|||
[weakSelf.callbackBlocks removeAllObjects];
|
||||
});
|
||||
self.dataTask = nil;
|
||||
self.imageData = nil;
|
||||
|
||||
NSOperationQueue *delegateQueue;
|
||||
if (self.unownedSession) {
|
||||
delegateQueue = self.unownedSession.delegateQueue;
|
||||
} else {
|
||||
delegateQueue = self.ownedSession.delegateQueue;
|
||||
}
|
||||
if (delegateQueue) {
|
||||
NSAssert(delegateQueue.maxConcurrentOperationCount == 1, @"NSURLSession delegate queue should be a serial queue");
|
||||
[delegateQueue addOperationWithBlock:^{
|
||||
weakSelf.imageData = nil;
|
||||
}];
|
||||
}
|
||||
|
||||
if (self.ownedSession) {
|
||||
[self.ownedSession invalidateAndCancel];
|
||||
self.ownedSession = nil;
|
||||
|
@ -304,48 +331,55 @@ didReceiveResponse:(NSURLResponse *)response
|
|||
if ((self.options & SDWebImageDownloaderProgressiveDownload) && self.expectedSize > 0) {
|
||||
// The following code is from http://www.cocoaintheshell.com/2011/05/progressive-images-download-imageio/
|
||||
// Thanks to the author @Nyx0uf
|
||||
|
||||
|
||||
// Get the image data
|
||||
NSData *imageData = [self.imageData copy];
|
||||
// Get the total bytes downloaded
|
||||
const NSInteger totalSize = self.imageData.length;
|
||||
|
||||
const NSInteger totalSize = imageData.length;
|
||||
// Get the finish status
|
||||
BOOL finished = (totalSize >= self.expectedSize);
|
||||
|
||||
if (!_imageSource) {
|
||||
_imageSource = CGImageSourceCreateIncremental(NULL);
|
||||
}
|
||||
// Update the data source, we must pass ALL the data, not just the new bytes
|
||||
CGImageSourceRef imageSource = CGImageSourceCreateWithData((__bridge CFDataRef)self.imageData, NULL);
|
||||
|
||||
if (width + height == 0) {
|
||||
CFDictionaryRef properties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, NULL);
|
||||
CGImageSourceUpdateData(_imageSource, (__bridge CFDataRef)imageData, finished);
|
||||
|
||||
if (_width + _height == 0) {
|
||||
CFDictionaryRef properties = CGImageSourceCopyPropertiesAtIndex(_imageSource, 0, NULL);
|
||||
if (properties) {
|
||||
NSInteger orientationValue = -1;
|
||||
CFTypeRef val = CFDictionaryGetValue(properties, kCGImagePropertyPixelHeight);
|
||||
if (val) CFNumberGetValue(val, kCFNumberLongType, &height);
|
||||
if (val) CFNumberGetValue(val, kCFNumberLongType, &_height);
|
||||
val = CFDictionaryGetValue(properties, kCGImagePropertyPixelWidth);
|
||||
if (val) CFNumberGetValue(val, kCFNumberLongType, &width);
|
||||
if (val) CFNumberGetValue(val, kCFNumberLongType, &_width);
|
||||
val = CFDictionaryGetValue(properties, kCGImagePropertyOrientation);
|
||||
if (val) CFNumberGetValue(val, kCFNumberNSIntegerType, &orientationValue);
|
||||
CFRelease(properties);
|
||||
|
||||
|
||||
// When we draw to Core Graphics, we lose orientation information,
|
||||
// which means the image below born of initWithCGIImage will be
|
||||
// oriented incorrectly sometimes. (Unlike the image born of initWithData
|
||||
// in didCompleteWithError.) So save it here and pass it on later.
|
||||
#if SD_UIKIT || SD_WATCH
|
||||
orientation = [[self class] orientationFromPropertyValue:(orientationValue == -1 ? 1 : orientationValue)];
|
||||
_orientation = [[self class] orientationFromPropertyValue:(orientationValue == -1 ? 1 : orientationValue)];
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (width + height > 0 && totalSize < self.expectedSize) {
|
||||
|
||||
if (_width + _height > 0 && !finished) {
|
||||
// Create the image
|
||||
CGImageRef partialImageRef = CGImageSourceCreateImageAtIndex(imageSource, 0, NULL);
|
||||
|
||||
CGImageRef partialImageRef = CGImageSourceCreateImageAtIndex(_imageSource, 0, NULL);
|
||||
|
||||
#if SD_UIKIT || SD_WATCH
|
||||
// Workaround for iOS anamorphic image
|
||||
if (partialImageRef) {
|
||||
const size_t partialHeight = CGImageGetHeight(partialImageRef);
|
||||
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
|
||||
CGContextRef bmContext = CGBitmapContextCreate(NULL, width, height, 8, width * 4, colorSpace, kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedFirst);
|
||||
CGContextRef bmContext = CGBitmapContextCreate(NULL, _width, _height, 8, _width * 4, colorSpace, kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedFirst);
|
||||
CGColorSpaceRelease(colorSpace);
|
||||
if (bmContext) {
|
||||
CGContextDrawImage(bmContext, (CGRect){.origin.x = 0.0f, .origin.y = 0.0f, .size.width = width, .size.height = partialHeight}, partialImageRef);
|
||||
CGContextDrawImage(bmContext, (CGRect){.origin.x = 0.0f, .origin.y = 0.0f, .size.width = _width, .size.height = partialHeight}, partialImageRef);
|
||||
CGImageRelease(partialImageRef);
|
||||
partialImageRef = CGBitmapContextCreateImage(bmContext);
|
||||
CGContextRelease(bmContext);
|
||||
|
@ -356,13 +390,14 @@ didReceiveResponse:(NSURLResponse *)response
|
|||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
if (partialImageRef) {
|
||||
#if SD_UIKIT || SD_WATCH
|
||||
UIImage *image = [UIImage imageWithCGImage:partialImageRef scale:1 orientation:orientation];
|
||||
UIImage *image = [UIImage imageWithCGImage:partialImageRef scale:1 orientation:_orientation];
|
||||
#elif SD_MAC
|
||||
UIImage *image = [[UIImage alloc] initWithCGImage:partialImageRef size:NSZeroSize];
|
||||
#endif
|
||||
CGImageRelease(partialImageRef);
|
||||
NSString *key = [[SDWebImageManager sharedManager] cacheKeyForURL:self.request.URL];
|
||||
UIImage *scaledImage = [self scaledImageForKey:key image:image];
|
||||
if (self.shouldDecompressImages) {
|
||||
|
@ -371,14 +406,16 @@ didReceiveResponse:(NSURLResponse *)response
|
|||
else {
|
||||
image = scaledImage;
|
||||
}
|
||||
CGImageRelease(partialImageRef);
|
||||
|
||||
[self callCompletionBlocksWithImage:image imageData:nil error:nil finished:NO];
|
||||
}
|
||||
}
|
||||
|
||||
if (imageSource) {
|
||||
CFRelease(imageSource);
|
||||
|
||||
if (finished) {
|
||||
if (_imageSource) {
|
||||
CFRelease(_imageSource);
|
||||
_imageSource = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -423,32 +460,50 @@ didReceiveResponse:(NSURLResponse *)response
|
|||
if ([self callbacksForKey:kCompletedCallbackKey].count > 0) {
|
||||
/**
|
||||
* If you specified to use `NSURLCache`, then the response you get here is what you need.
|
||||
* if you specified to only use cached data via `SDWebImageDownloaderIgnoreCachedResponse`,
|
||||
* the response data will be nil.
|
||||
* So we don't need to check the cache option here, since the system will obey the cache option
|
||||
*/
|
||||
if (self.imageData) {
|
||||
UIImage *image = [UIImage sd_imageWithData:self.imageData];
|
||||
NSString *key = [[SDWebImageManager sharedManager] cacheKeyForURL:self.request.URL];
|
||||
image = [self scaledImageForKey:key image:image];
|
||||
|
||||
// Do not force decoding animated GIFs
|
||||
if (!image.images) {
|
||||
if (self.shouldDecompressImages) {
|
||||
if (self.options & SDWebImageDownloaderScaleDownLargeImages) {
|
||||
#if SD_UIKIT || SD_WATCH
|
||||
image = [UIImage decodedAndScaledDownImageWithImage:image];
|
||||
[self.imageData setData:UIImagePNGRepresentation(image)];
|
||||
NSData *imageData = [self.imageData copy];
|
||||
if (imageData) {
|
||||
UIImage *image = [UIImage sd_imageWithData:imageData];
|
||||
/** if you specified to only use cached data via `SDWebImageDownloaderIgnoreCachedResponse`,
|
||||
* then we should check if the cached data is equal to image data
|
||||
*/
|
||||
if (self.options & SDWebImageDownloaderIgnoreCachedResponse && [self.cachedData isEqualToData:imageData]) {
|
||||
// call completion block with nil
|
||||
[self callCompletionBlocksWithImage:nil imageData:nil error:nil finished:YES];
|
||||
} else {
|
||||
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
|
||||
} else {
|
||||
image = [UIImage decodedImageWithImage:image];
|
||||
}
|
||||
|
||||
if (shouldDecode) {
|
||||
if (self.shouldDecompressImages) {
|
||||
if (self.options & SDWebImageDownloaderScaleDownLargeImages) {
|
||||
#if SD_UIKIT || SD_WATCH
|
||||
image = [UIImage decodedAndScaledDownImageWithImage:image];
|
||||
imageData = UIImagePNGRepresentation(image);
|
||||
#endif
|
||||
} else {
|
||||
image = [UIImage decodedImageWithImage:image];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (CGSizeEqualToSize(image.size, CGSizeZero)) {
|
||||
[self callCompletionBlocksWithError:[NSError errorWithDomain:SDWebImageErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey : @"Downloaded image has 0 pixels"}]];
|
||||
} else {
|
||||
[self callCompletionBlocksWithImage:image imageData:self.imageData error:nil finished:YES];
|
||||
if (CGSizeEqualToSize(image.size, CGSizeZero)) {
|
||||
[self callCompletionBlocksWithError:[NSError errorWithDomain:SDWebImageErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey : @"Downloaded image has 0 pixels"}]];
|
||||
} else {
|
||||
[self callCompletionBlocksWithImage:image imageData:imageData error:nil finished:YES];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
[self callCompletionBlocksWithError:[NSError errorWithDomain:SDWebImageErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey : @"Image data is nil"}]];
|
||||
|
|
|
@ -71,11 +71,10 @@ static inline NSString * backgroundImageURLKeyForState(UIControlState state) {
|
|||
completed:(nullable SDExternalCompletionBlock)completedBlock {
|
||||
if (!url) {
|
||||
[self.imageURLStorage removeObjectForKey:imageURLKeyForState(state)];
|
||||
return;
|
||||
} else {
|
||||
self.imageURLStorage[imageURLKeyForState(state)] = url;
|
||||
}
|
||||
|
||||
self.imageURLStorage[imageURLKeyForState(state)] = url;
|
||||
|
||||
__weak typeof(self)weakSelf = self;
|
||||
[self sd_internalSetImageWithURL:url
|
||||
placeholderImage:placeholder
|
||||
|
@ -131,11 +130,10 @@ static inline NSString * backgroundImageURLKeyForState(UIControlState state) {
|
|||
completed:(nullable SDExternalCompletionBlock)completedBlock {
|
||||
if (!url) {
|
||||
[self.imageURLStorage removeObjectForKey:backgroundImageURLKeyForState(state)];
|
||||
return;
|
||||
} else {
|
||||
self.imageURLStorage[backgroundImageURLKeyForState(state)] = url;
|
||||
}
|
||||
|
||||
self.imageURLStorage[backgroundImageURLKeyForState(state)] = url;
|
||||
|
||||
__weak typeof(self)weakSelf = self;
|
||||
[self sd_internalSetImageWithURL:url
|
||||
placeholderImage:placeholder
|
||||
|
|
|
@ -9,10 +9,17 @@
|
|||
#ifdef SD_WEBP
|
||||
|
||||
#import "UIImage+WebP.h"
|
||||
#import "NSImage+WebCache.h"
|
||||
|
||||
#if __has_include(<webp/decode.h>) && __has_include(<webp/mux_types.h>) && __has_include(<webp/demux.h>)
|
||||
#import <webp/decode.h>
|
||||
#import <webp/mux_types.h>
|
||||
#import <webp/demux.h>
|
||||
#else
|
||||
#import "webp/decode.h"
|
||||
#import "webp/mux_types.h"
|
||||
#import "webp/demux.h"
|
||||
#import "NSImage+WebCache.h"
|
||||
#endif
|
||||
|
||||
#import "objc/runtime.h"
|
||||
|
||||
|
@ -44,20 +51,6 @@ static void FreeImageData(void *info, const void *data, size_t size) {
|
|||
}
|
||||
|
||||
uint32_t flags = WebPDemuxGetI(demuxer, WEBP_FF_FORMAT_FLAGS);
|
||||
if (!(flags & ANIMATION_FLAG)) {
|
||||
// for static single webp image
|
||||
UIImage *staticImage = [self sd_rawWebpImageWithData:webpData];
|
||||
WebPDemuxDelete(demuxer);
|
||||
return staticImage;
|
||||
}
|
||||
|
||||
WebPIterator iter;
|
||||
if (!WebPDemuxGetFrame(demuxer, 1, &iter)) {
|
||||
WebPDemuxReleaseIterator(&iter);
|
||||
WebPDemuxDelete(demuxer);
|
||||
return nil;
|
||||
}
|
||||
|
||||
#if SD_UIKIT || SD_WATCH
|
||||
int loopCount = WebPDemuxGetI(demuxer, WEBP_FF_LOOP_COUNT);
|
||||
int frameCount = WebPDemuxGetI(demuxer, WEBP_FF_FRAME_COUNT);
|
||||
|
@ -72,8 +65,38 @@ static void FreeImageData(void *info, const void *data, size_t size) {
|
|||
}
|
||||
CGContextRef canvas = CGBitmapContextCreate(NULL, canvasWidth, canvasHeight, 8, 0, SDCGColorSpaceGetDeviceRGB(), bitmapInfo);
|
||||
if (!canvas) {
|
||||
WebPDemuxDelete(demuxer);
|
||||
return nil;
|
||||
}
|
||||
|
||||
if (!(flags & ANIMATION_FLAG)) {
|
||||
// for static single webp image
|
||||
UIImage *staticImage = [self sd_rawWebpImageWithData:webpData];
|
||||
if (staticImage) {
|
||||
// draw on CGBitmapContext can reduce memory usage
|
||||
CGImageRef imageRef = staticImage.CGImage;
|
||||
size_t width = CGImageGetWidth(imageRef);
|
||||
size_t height = CGImageGetHeight(imageRef);
|
||||
CGContextDrawImage(canvas, CGRectMake(0, 0, width, height), imageRef);
|
||||
CGImageRef newImageRef = CGBitmapContextCreateImage(canvas);
|
||||
#if SD_UIKIT || SD_WATCH
|
||||
staticImage = [[UIImage alloc] initWithCGImage:newImageRef];
|
||||
#else
|
||||
staticImage = [[UIImage alloc] initWithCGImage:newImageRef size:NSZeroSize];
|
||||
#endif
|
||||
CGImageRelease(newImageRef);
|
||||
}
|
||||
WebPDemuxDelete(demuxer);
|
||||
CGContextRelease(canvas);
|
||||
return staticImage;
|
||||
}
|
||||
|
||||
// for animated webp image
|
||||
WebPIterator iter;
|
||||
if (!WebPDemuxGetFrame(demuxer, 1, &iter)) {
|
||||
WebPDemuxReleaseIterator(&iter);
|
||||
WebPDemuxDelete(demuxer);
|
||||
CGContextRelease(canvas);
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
@ -84,33 +107,36 @@ static void FreeImageData(void *info, const void *data, size_t size) {
|
|||
#endif
|
||||
|
||||
do {
|
||||
UIImage *image;
|
||||
if (iter.blend_method == WEBP_MUX_BLEND) {
|
||||
image = [self sd_blendWebpImageWithCanvas:canvas iterator:iter];
|
||||
} else {
|
||||
image = [self sd_nonblendWebpImageWithCanvas:canvas iterator:iter];
|
||||
}
|
||||
|
||||
if (!image) {
|
||||
continue;
|
||||
}
|
||||
|
||||
[images addObject:image];
|
||||
|
||||
@autoreleasepool {
|
||||
UIImage *image;
|
||||
if (iter.blend_method == WEBP_MUX_BLEND) {
|
||||
image = [self sd_blendWebpImageWithCanvas:canvas iterator:iter];
|
||||
} else {
|
||||
image = [self sd_nonblendWebpImageWithCanvas:canvas iterator:iter];
|
||||
}
|
||||
|
||||
if (!image) {
|
||||
continue;
|
||||
}
|
||||
|
||||
[images addObject:image];
|
||||
|
||||
#if SD_MAC
|
||||
break;
|
||||
break;
|
||||
#else
|
||||
|
||||
int duration = iter.duration;
|
||||
if (duration <= 10) {
|
||||
// WebP standard says 0 duration is used for canvas updating but not showing image, but actually Chrome and other implementations set it to 100ms if duration is lower or equal than 10ms
|
||||
// Some animated WebP images also created without duration, we should keep compatibility
|
||||
duration = 100;
|
||||
}
|
||||
totalDuration += duration;
|
||||
size_t count = images.count;
|
||||
durations[count - 1] = duration;
|
||||
|
||||
int duration = iter.duration;
|
||||
if (duration <= 10) {
|
||||
// WebP standard says 0 duration is used for canvas updating but not showing image, but actually Chrome and other implementations set it to 100ms if duration is lower or equal than 10ms
|
||||
// Some animated WebP images also created without duration, we should keep compatibility
|
||||
duration = 100;
|
||||
}
|
||||
totalDuration += duration;
|
||||
size_t count = images.count;
|
||||
durations[count - 1] = duration;
|
||||
#endif
|
||||
}
|
||||
|
||||
} while (WebPDemuxNextFrame(&iter));
|
||||
|
||||
WebPDemuxReleaseIterator(&iter);
|
||||
|
|
|
@ -173,7 +173,7 @@
|
|||
DA248D461954721A00390AB0 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0800;
|
||||
LastUpgradeCheck = 0900;
|
||||
};
|
||||
buildConfigurationList = DA248D491954721A00390AB0 /* Build configuration list for PBXProject "SDWebImage Tests" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
|
@ -290,12 +290,18 @@
|
|||
DA248D4A1954721A00390AB0 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
|
@ -316,12 +322,18 @@
|
|||
DA248D4B1954721A00390AB0 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0800"
|
||||
LastUpgradeVersion = "0900"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -26,6 +26,7 @@
|
|||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
codeCoverageEnabled = "YES">
|
||||
<Testables>
|
||||
|
@ -47,6 +48,7 @@
|
|||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
- (nullable SDWebImageDownloadToken *)addProgressCallback:(SDWebImageDownloaderProgressBlock)progressBlock
|
||||
completedBlock:(SDWebImageDownloaderCompletedBlock)completedBlock
|
||||
forURL:(nullable NSURL *)url
|
||||
createCallback:(SDWebImageDownloaderOperation *(^)())createCallback;
|
||||
createCallback:(SDWebImageDownloaderOperation *(^)(void))createCallback;
|
||||
@end
|
||||
|
||||
/**
|
||||
|
|
|
@ -73,7 +73,7 @@ NSString *workingImageURL = @"http://s3.amazonaws.com/fast-image-cache/demo-imag
|
|||
XCTFail(@"Image should be in cache");
|
||||
}
|
||||
}];
|
||||
[self waitForExpectationsWithTimeout:kAsyncTestTimeout handler:nil];
|
||||
[self waitForExpectationsWithCommonTimeout];
|
||||
}
|
||||
|
||||
- (void)test05DiskImageExistsForURL {
|
||||
|
@ -108,4 +108,23 @@ NSString *workingImageURL = @"http://s3.amazonaws.com/fast-image-cache/demo-imag
|
|||
[self waitForExpectationsWithCommonTimeout];
|
||||
}
|
||||
|
||||
- (void)test07ThatLoadImageWithSDWebImageRefreshCachedWorks {
|
||||
XCTestExpectation *expectation = [self expectationWithDescription:@"Image download twice with SDWebImageRefresh failed"];
|
||||
NSURL *originalImageURL = [NSURL URLWithString:@"http://s3.amazonaws.com/fast-image-cache/demo-images/FICDDemoImage007.jpg"];
|
||||
[[SDImageCache sharedImageCache] clearDiskOnCompletion:nil];
|
||||
|
||||
[[SDWebImageManager sharedManager] loadImageWithURL:originalImageURL options:SDWebImageRefreshCached progress:nil completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL) {
|
||||
expect(image).toNot.beNil();
|
||||
expect(error).to.beNil();
|
||||
// #1993, load image with SDWebImageRefreshCached twice should not fail if the first time success.
|
||||
|
||||
[[SDWebImageManager sharedManager] loadImageWithURL:originalImageURL options:SDWebImageRefreshCached progress:nil completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL) {
|
||||
expect(image).toNot.beNil();
|
||||
expect(error).to.beNil();
|
||||
[expectation fulfill];
|
||||
}];
|
||||
}];
|
||||
[self waitForExpectationsWithCommonTimeout];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -15,11 +15,11 @@
|
|||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>4.1.0</string>
|
||||
<string>4.1.2</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>4.1.0</string>
|
||||
<string>4.1.2</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string></string>
|
||||
</dict>
|
||||
|
|
Loading…
Reference in New Issue