Compare commits

..

13 Commits
master ... 4.0

Author SHA1 Message Date
Bogdan Poplauschi 93d009f82d Added AFNetworking files to targets 2015-07-14 15:06:19 +03:00
Bogdan Poplauschi dd4582ff10 Created SDWebImage+All target that includes all the files, so we can easily include it into the Demo app 2015-07-14 14:59:01 +03:00
Bogdan Poplauschi 0414ec5291 Updated project and scheme 2015-07-14 00:53:04 +03:00
Bogdan Poplauschi 08db889da1 Switched UIImage+GIF to use FLAnimatedImage. Replaced #908 and added @3x support for the GIF imageNamed 2015-07-14 00:33:52 +03:00
Bogdan Poplauschi 21ed4e2aa7 Added another test gif 2015-07-14 00:32:19 +03:00
Bogdan Poplauschi a9649e44da Added FLAnimatedImage classes to project, created a SDWebImage+GIF target, scheme 2015-07-14 00:19:23 +03:00
Bogdan Poplauschi 5f4e85159e UIImage+WebP doesn't need to be built with the MapKit target 2015-07-14 00:00:58 +03:00
Bogdan Poplauschi a19fb57c98 Updated references to new submodules to https urls, trying to fix travis 2015-07-13 23:44:27 +03:00
Bogdan Poplauschi 7c2b74070d Using AFNetworking latest release commit and FLAnimatedImage uiimage_subclass branch 2015-07-13 23:25:02 +03:00
Bogdan Poplauschi 3aa3f4b9dc Added FLAnimatedImage as submodule 2015-07-13 23:25:02 +03:00
Bogdan Poplauschi 3f63d7a60e Added AFNetworking as submodule 2015-07-13 23:25:02 +03:00
Bogdan Poplauschi 19431d0f81 Renamed SDWebImageManager `downloadImageWithURL:options:progress:completed:` to `loadImageWithURL:options:progress:completed:` as it makes more sense, since we check the cache first and download only if needed 2015-07-13 23:25:02 +03:00
Bogdan Poplauschi f1709a9214 Fixed #774 - remove deprecated methods. Since 4.0 is a major release, we don't need the backwards compatible methods 2015-07-13 23:25:02 +03:00
62 changed files with 1830 additions and 2287 deletions

View File

@ -1,42 +0,0 @@
# Contributing to SDWebImage
We want to make contributing to this project as easy and transparent as possible. Here are a few guidelines for making all our lives easier.
## Asking questions
We don't use GitHub as a support forum. For any usage questions that are not specific to the project itself, please ask on [Stack Overflow](https://stackoverflow.com/) instead. By doing so, you'll be more likely to quickly solve your problem, and you'll allow anyone else with the same question to find the answer. This also allows maintainers to focus on improving the project for others.
## Reporting Issues
A great way to contribute to the project is to send a detailed issue when you encounter an problem.
It is very important to check for the same problem or suggestion in the project's issue list first. If you find a match, just add a small comment there.
Doing this helps prioritize the most common problems and requests.
When reporting issues, please include the following:
- The platform name and version (e.g. iOS 8.1)
- The library version
- The integration method (e.g. CocoaPods/Carthage/manually)
- The version of Xcode you're using
- The full output of any stack trace or compiler error
- A small demo project that replicates the issue (especially if the way to reproduce the issue is not straight-forward)
- Any other details that would be useful in understanding the problem
This information will help us review and fix your issue faster.
Please do not be offended if we close your issue and reference this document.
If you believe the issue is truely a fault in the projects codebase, re-open it.
## Pull Requests
We gladly accept any PR's assuming they are well written, documented ( if necessary ) and preferably have test code.
If you're unsure if we'll accept a new feature please open an issue requesting it and we can have a discussion before you code and submit a PR.
Checklist:
- Fork the repo and create your branch from the latest master (to minimize the conflicts)
- If you've added code that should be tested, add tests.
- If you've changed APIs, update the documentation.
- Ensure the test suite passes.
- Make sure your code lints (pod lib lint)

View File

@ -1,23 +0,0 @@
### New Issue Checklist
* [ ] I have read and understood the [CONTRIBUTING guide](https://github.com/rs/SDWebImage/blob/master/.github/CONTRIBUTING.md)
* [ ] I have read the [Documentation](http://cocoadocs.org/docsets/SDWebImage/)
* [ ] I have searched for a similar issue in the [project](https://github.com/rs/SDWebImage/issues) and found none
### Issue Info
Info | Value |
-------------------------|-------------------------------------|
Platform Name | e.g. ios / tvos
Platform Version | e.g. 8.0
SDWebImage Version | e.g. 3.7.6
Integration Method | e.g. carthage / cocoapods / manually
Xcode Version | e.g. Xcode 7.3
Repro rate | e.g. all the time (100%) / sometimes x% / only once
Repro with our demo prj | e.g. does it happen with our demo project?
Demo project link | e.g. link to a demo project that highlights the issue
### Issue Description and Steps
Please fill in the detailed description of the issue (full output of any stack trace, compiler error, ...) and the steps to reproduce the issue.

View File

@ -1,18 +0,0 @@
### New Pull Request Checklist
* [ ] I have read and understood the [CONTRIBUTING guide](https://github.com/rs/SDWebImage/blob/master/.github/CONTRIBUTING.md)
* [ ] I have read the [Documentation](http://cocoadocs.org/docsets/SDWebImage/)
* [ ] I have searched for a similar pull request in the [project](https://github.com/rs/SDWebImage/pulls) and found none
* [ ] I have updated this branch with the latest master to avoid conflicts (via merge from master or rebase)
* [ ] I have added the required tests to prove the fix/feature I am adding
* [ ] I have updated the documentation (if necesarry)
* [ ] I have run the tests and they pass
* [ ] I have run the lint and it passes (`pod lib lint`)
This merge request fixes / reffers to the following issues: ...
### Pull Request Description
...

3
.gitignore vendored
View File

@ -18,7 +18,6 @@ DerivedData
*.hmap *.hmap
*.ipa *.ipa
*.xcuserstate *.xcuserstate
*.xcscmblueprint
# CocoaPods # CocoaPods
# #
@ -27,4 +26,4 @@ DerivedData
# http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
# #
Pods/ Pods/
Podfile.lock Podfile.lock

8
.gitmodules vendored
View File

@ -1,3 +1,9 @@
[submodule "Vendors/libwebp"] [submodule "Vendors/libwebp"]
path = Vendors/libwebp path = Vendors/libwebp
url = https://github.com/webmproject/libwebp url = https://chromium.googlesource.com/webm/libwebp
[submodule "Vendors/AFNetworking"]
path = Vendors/AFNetworking
url = https://github.com/AFNetworking/AFNetworking.git
[submodule "Vendors/FLAnimatedImage"]
path = Vendors/FLAnimatedImage
url = https://github.com/Flipboard/FLAnimatedImage.git

View File

@ -1,27 +1,24 @@
language: objective-c language: objective-c
osx_image: xcode7.1
before_install: before_install:
- export LANG=en_US.UTF-8 - export LANG=en_US.UTF-8
- env - env
- locale - locale
- gem install cocoapods --no-rdoc --no-ri --no-document --quiet - gem install cocoapods --quiet
- pod --version - pod --version
- pod setup --silent > /dev/null - pod setup --silent
- pod repo update --silent - pod repo update --silent
script: script:
- pod lib lint --allow-warnings - pod lib lint --allow-warnings
- xctool -workspace SDWebImage.xcworkspace -scheme 'SDWebImage' -sdk iphonesimulator build - xctool -workspace SDWebImage.xcworkspace -scheme 'SDWebImage' -sdk iphonesimulator -arch i386 build
- xctool -workspace SDWebImage.xcworkspace -scheme 'SDWebImage+WebP' -sdk iphonesimulator build - xctool -workspace SDWebImage.xcworkspace -scheme 'SDWebImage+WebP' -sdk iphonesimulator -arch i386 build
- xctool -workspace SDWebImage.xcworkspace -scheme 'SDWebImage+MKAnnotation' -sdk iphonesimulator build - xctool -workspace SDWebImage.xcworkspace -scheme 'SDWebImage+MKAnnotation' -sdk iphonesimulator -arch i386 build
- xctool -workspace SDWebImage.xcworkspace -scheme 'SDWebImage Demo' -sdk iphonesimulator build - xctool -workspace SDWebImage.xcworkspace -scheme 'SDWebImage Demo' -sdk iphonesimulator -arch i386 build
- pod install --project-directory=Tests - pod install --project-directory=Tests
- xctool -workspace SDWebImage.xcworkspace -scheme 'SDWebImage' -sdk iphonesimulator clean - xcodebuild -workspace SDWebImage.xcworkspace -scheme 'Tests' -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 6,OS=latest' test
- xctool -workspace SDWebImage.xcworkspace -scheme 'Tests' -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 6,OS=latest' test

View File

@ -1,283 +0,0 @@
## [3.8.1 Patch release for 3.8.0 on Jun 7th, 2016](https://github.com/rs/SDWebImage/releases/tag/3.8.1)
#### Fixes:
- SDWebImage 3.8.0 get wrong image #1589 - the issue was caused by the changes in 3.8.0 (Removed the URL query params from the filename (key) fb0cdb6d 1bf62d4 #1584 - fixes #1433 #1553 #1583 #1585) - Reverted.
- Note: The solution for those issues (i.e. #1433 #1553) is to set the `SDWebImageManager` `cacheKeyFilter` block and do their own calculations there.
## [3.8.0 Minor release - Replaces NSURLConnection (deprecated) with NSURLSession - on Jun 6th, 2016](https://github.com/rs/SDWebImage/releases/tag/3.8.0)
#### Infrastructure:
- Had to update the iOS deployment target to 7.0 from 5 - 6545a3a
#### Features:
- Replace deprecated `NSURLConnection` with `NSURLSession` #1578 #1586 - fixes #1291 #1318 #823 #1566 #1515
- Allow to customise cache and image downloader instances used with `SDWebImageManager` 86fc47bf7b - fixes #1398 #870
#### Fixes:
- Removed the URL query params from the filename (key) fb0cdb6d 1bf62d4 #1584 - fixes #1433 #1553 #1583 #1585
- Fixed the WebP build with the official 1.0.0 CocoaPods release f1a471e - fixes #1444
- Updated doc: `removeImageForKey:` not synchronous e6e5c51 - fixes #1379 #1415
## [3.7.6 Patch release for 3.7.0 on May 8th, 2016](https://github.com/rs/SDWebImage/releases/tag/3.7.6)
#### Infrastructure:
- Changed the **libwebp git url** so that people from China can access it - #1390 (from `https://chromium.googlesource.com/webm/libwebp` to `https://github.com/webmproject/libwebp`)
#### Features:
- Added `cancelAllDownloads` method to `SDWebImageDownloader` #1504
- Added API to save image `NSData` to disk cache: `[SDImageCache storeImageDataToDisk:forKey:]` #1453
#### Fixes:
- Fix #1449: Version 3.7.5 breaks semantic versioning (removes public API). Re-added `sd_setImageWithPreviousCachedImageWithURL:andPlaceholderImage:options:progress:completed:` and deprecated it. Will remove it in 4.0.0 b40124c
- Fix `CGContextDrawImage: invalid context 0x0` - #1496 (fixes #1401 #1454 #1457)
- Fix `CGBitmapContextCreateImage: invalid context 0x0` - #1464 (fixes #1423)
- Fix changed image size when loading from disk #1540 (fixes #1437)
- Repair memory release in the iPad environment #1549 (had to switch `#if TARGET_OS_IPHONE` to `#if TARGET_OS_IOS`)
- Fixed completion logic in `MKAnnotationView+WebCache` #1547
- Optimize the decoder to avoid unwanted blended layer - #1527 (fixes #1524)
- Protect against malformed frame for GIFs - #1447
- updated doc: #1462 #1466 #1486 #1532 #1461
## [3.7.5 Patch release for 3.7.0 on Jan 21st, 2016](https://github.com/rs/SDWebImage/releases/tag/3.7.5)
- fixed #1425 and #1426 - Continuation of Fix #1366, addresses #1350 and reverts a part of #1221 - from commit 6406d8e, the wrong usage of `dispatch_apply`
- fixed #1422 - Added a fallback for #976 so that if there are images saved with the old format (no extension), they can still be loaded
## [3.7.4 Patch release for 3.7.0 with tvOS support on Jan 8th, 2016](https://github.com/rs/SDWebImage/releases/tag/3.7.4)
#### Updates
- bumped `libwep` version to `0.4.4`
#### Features:
- added tvOS support #1327 and #1358 - fix #1368 and #1302
#### Fixes:
- #1217 contains several of the above fixes
- fix #391 -> option to cache only on Disk. will replace #1130
- fix #343 -> iCloud backup Option
- fix #371 -> CGBitmapContextCreate: unsupported parameter combination + #1268 #1412 #1340
- fix #576 -> scale set to screen scale
- fix #1035 -> progress queue with dispatch_async
- new feature -> activity indicator using auto layout. The activity indicator feature will replace #131
- #1218 progress callbacks now report on main thread - fixes #1035
- #1321 Added a new constructor to SDWebImagePrefetcher - replaces #956
- #976 append the original path extension to the hash filename - fixes #967
- replaced #999 with #1221
- added cache tests #1125
- #1236 fixes #1203
- bf899e2 fixes #1261 #1263 compilation issue CocoaPods vs non-CocoaPods
- #1367 fixes a bug where image scale & orientation are ignored when decoding / decompressing an image
- cac21e1 fixes #1366, addresses #1350 and reverts a part of #1221 - from commit 6406d8e, the wrong usage of dispatch_apply
- #1363 fixes #1361 sd_cancelBackgroundImageLoadForState
- #1348 Create a strong ref of weakOperation in the entry of The image download subOperation, use the strong ref instead weakOperation. At the same time, repair some logic of the 'If cancelled'
- dcb7985 replaces #1345 - Load local credential file
- #1323 don't to perform download if url is "" but not nil
- #1310 Added support for SDWebImageAvoidAutoSetImage option to UIButton and highlighted UIImageView categories
- #1308 Added Swift installation tips
- 32923fa Xcode 7.1 updates
- #1297 cleaner implementation of failedUrl error handling - fixes #1275
- #1280 Fix sd_animatedImageByScalingAndCroppingToSize
- Remove logging from the image prefetcher - #1276
- Fix typos #1256 #1257 #1258 #1331 #1290
## [3.7.3 Patch release for 3.7.0 with iOS8+ framework and Carthage on Jun 13th, 2015](https://github.com/rs/SDWebImage/releases/tag/3.7.3)
- Adds support for **iOS 8+ Framework and Carthage** [#1071](https://github.com/rs/SDWebImage/pull/1071) [#1081](https://github.com/rs/SDWebImage/pull/1081) [#1101](https://github.com/rs/SDWebImage/pull/1101)
- [Refactor] Use `NSMutableSet` for failed URLs' storage instead of array [#1076](https://github.com/rs/SDWebImage/pull/1076)
- Make a constant for the error domain [#1011](https://github.com/rs/SDWebImage/pull/1011)
- Improve operation behavior [#988](https://github.com/rs/SDWebImage/pull/988)
- Bug fix: `Collection <__NSArrayM: > was mutated while being enumerated` [#985](https://github.com/rs/SDWebImage/pull/985)
- added `SDWebImageAvoidAutoSetImage` option to avoid automatic image addition in `UIImageView` and let developer to do it himself [#1188](https://github.com/rs/SDWebImage/pull/1188)
- Added support for custom disk cache folder with fall back for caches directory [#1153](https://github.com/rs/SDWebImage/pull/1153)
- Added some files to the workspace so they are easier to edit [8431481](https://github.com/rs/SDWebImage/commit/8431481)
- Doc update [72ed897](https://github.com/rs/SDWebImage/commit/72ed897) [7f99c01](https://github.com/rs/SDWebImage/commit/7f99c01) [#1016](https://github.com/rs/SDWebImage/pull/1016) [#1038](https://github.com/rs/SDWebImage/pull/1038) [#1045](https://github.com/rs/SDWebImage/pull/1045)
- [Memory Issue] Clear `SDWebImagePrefetcher` `progressBlock` when it has completed [#1017](https://github.com/rs/SDWebImage/pull/1017)
- avoid warning `<Error>: ImageIO: CGImageSourceCreateWithData data parameter is nil` if `imageData` is nil [88ee3c6](https://github.com/rs/SDWebImage/commit/88ee3c6) [#1018](https://github.com/rs/SDWebImage/pull/1018)
- allow override `diskCachePath` [#1041](https://github.com/rs/SDWebImage/pull/1041)
- Use `__typeof(self)` when assigning `weak` reference for block [#1054](https://github.com/rs/SDWebImage/pull/1054)
- [Refactor] Implement cache cost calculation as a inline function [#1075](https://github.com/rs/SDWebImage/pull/1075)
- @3x support [9620fff](https://github.com/rs/SDWebImage/commit/9620fff) [#1005](https://github.com/rs/SDWebImage/pull/1005)
- Fix parenthesis to avoid crashes [#1104](https://github.com/rs/SDWebImage/pull/1104)
- Add `NSCache` countLimit property [#1140](https://github.com/rs/SDWebImage/pull/1140)
- `failedURLs` can be removed at the appropriate time [#1111](https://github.com/rs/SDWebImage/pull/1111)
- Purge `NSCache` on system memory notifications [#1143](https://github.com/rs/SDWebImage/pull/1143)
- Determines at runtime is `UIApplication` is available as per [#1082](https://github.com/rs/SDWebImage/issues/1082) [#1085](https://github.com/rs/SDWebImage/pull/1085)
- Fixes http://git.chromium.org/webm/libwebp.git/info/refs not valid [#1175](https://github.com/rs/SDWebImage/pull/1175) + Reverted [#1193](https://github.com/rs/SDWebImage/pull/1193) + [#1177](https://github.com/rs/SDWebImage/pull/1177)
- 404 image url was causing the test to fail [0e761f4](https://github.com/rs/SDWebImage/commit/0e761f4)
- Fix for transparency being lost in transformed images. [#1121](https://github.com/rs/SDWebImage/pull/1121)
- Add handling for additional error codes that shouldn't be considered a permanent failure [#1159](https://github.com/rs/SDWebImage/pull/1159)
- add webp accepted content type only if `WebP` enabled [#1178](https://github.com/rs/SDWebImage/pull/1178)
- fix `ImageIO: CGImageSourceCreateWithData` data parameter is nil [#1167](https://github.com/rs/SDWebImage/pull/1167)
- Applied patch for issue [#1074](https://github.com/rs/SDWebImage/issues/1074) SDWebImage residing in swift module breaks the debugger [#1138](https://github.com/rs/SDWebImage/pull/1138)
- Fixed URLs with trailing parameters get assigned an incorrect image scale value [#1157](https://github.com/rs/SDWebImage/issues/1157) [#1158](https://github.com/rs/SDWebImage/pull/1158)
- Add newline to avoid compiler warning in `WebImage.h` [#1199](https://github.com/rs/SDWebImage/pull/1199)
## [3.7.2 Updated patch release for 3.7.0 on Mar 17th, 2015](https://github.com/rs/SDWebImage/releases/tag/3.7.2)
#### Updates
- bumped `libwep` version to `0.4.3`
#### Features:
- implement `SDWebImageDownloaderAllowInvalidSSLCertificates` option - [#937](https://github.com/rs/SDWebImage/pull/937)
- flag to transform animated images (`SDWebImageTransformAnimatedImage`) - [#703](https://github.com/rs/SDWebImage/pull/703)
- allows user to override default `SDWebImageDownloaderOperation` - [#876](https://github.com/rs/SDWebImage/pull/876)
- adds option to decompress images and select prefetcher queue - [#996](https://github.com/rs/SDWebImage/pull/996)
#### Fixes:
- fixed [#809](https://github.com/rs/SDWebImage/issues/809) `cancelAll` crash - [#838](https://github.com/rs/SDWebImage/pull/838)
- fixed [#900](https://github.com/rs/SDWebImage/issues/900) by adding a new flag `SD_LOG_NONE` that allows silencing the SD logs from the Prefetcher
- fixed [#895](https://github.com/rs/SDWebImage/issues/895) unsafe setImage in `setImageWithURL:` - [#896](https://github.com/rs/SDWebImage/pull/896)
- fix `NSNotificationCenter` dispatch on subthreads - [#987](https://github.com/rs/SDWebImage/pull/987)
- fix `SDWebImageDownloader` threading issue - [#104](https://github.com/rs/SDWebImage/pull/104)6
- fixed duplicate failed urls are added into `failedURLs` - [#994](https://github.com/rs/SDWebImage/pull/994)
- increased default `maxConcurrentOperationCount`, fixes [#527](https://github.com/rs/SDWebImage/issues/527) - [#897](https://github.com/rs/SDWebImage/pull/897)
- handle empty urls `NSArray` - [#929](https://github.com/rs/SDWebImage/pull/929)
- decoding webp, depends on source image data alpha status - [#936](https://github.com/rs/SDWebImage/pull/936)
- fix [#610](https://github.com/rs/SDWebImage/issues/610) display progressive jpeg issue - [#840](https://github.com/rs/SDWebImage/pull/840)
- the code from `SDWebImageDownloaderOperation connection:didFailWithError:` should match the code from `connectionDidFinishLoading:`. This fixes [#872](https://github.com/rs/SDWebImage/issues/872) - [7f39e5e](https://github.com/rs/SDWebImage/commit/7f39e5e)
- `304 - Not Modified` HTTP status code handling - [#942](https://github.com/rs/SDWebImage/pull/942)
- cost compute fix - [#941](https://github.com/rs/SDWebImage/pull/941)
- initialise `kPNGSignatureData` data - [#981](https://github.com/rs/SDWebImage/pull/981)
#### Documentation
- documentation updated
## [3.7.1 Patch release for 3.7.0 on Jul 23rd, 2014](https://github.com/rs/SDWebImage/releases/tag/3.7.1)
- fixed `sd_imageOrientationFromImageData:` crash if imageSource is nil - [#819](https://github.com/rs/SDWebImage/pull/819) [#813](https://github.com/rs/SDWebImage/pull/813) [#808](https://github.com/rs/SDWebImage/issues/808) [#828](https://github.com/rs/SDWebImage/issues/828) - temporary fix
- fixed `SDWebImageCombinedOperation cancel` crash (also visible as `SDWebImageManager cancelAll`) - [28109c4](https://github.com/rs/SDWebImage/commit/28109c4) [#798](https://github.com/rs/SDWebImage/issues/798) [#809](https://github.com/rs/SDWebImage/issues/809)
- fixed duplicate symbols when using with webp via pods - [#795](https://github.com/rs/SDWebImage/pull/795)
- fixed missing `mark` from `pragma mark` - [#827](https://github.com/rs/SDWebImage/pull/827)
## [3.7.0 Xcode6, arm64, highlight UIImageView, imageURL ref, NTLM, ... on Jul 14th, 2014](https://github.com/rs/SDWebImage/releases/tag/3.7.0)
## Features
- Add category for imageView's highlighted state `UIImageView+HighlightedWebCache` - [#646](https://github.com/rs/SDWebImage/pull/646) [#765](https://github.com/rs/SDWebImage/pull/765)
- Keep a reference to the image URL - [#560](https://github.com/rs/SDWebImage/pull/560)
- Pass imageURL in completedBlock - [#770](https://github.com/rs/SDWebImage/pull/770)
- Implemented NTLM auth support. Replaced deprecated auth challenge methods from `NSURLConnectionDelegate` - [#711](https://github.com/rs/SDWebImage/pull/711) [50c4d1d](https://github.com/rs/SDWebImage/commit/50c4d1d)
- Ability to suspend image downloaders `SDWebImageDownloader setSuspended:` - [#734](https://github.com/rs/SDWebImage/pull/734)
- Delay the loading of the placeholder image until after load - [#701](https://github.com/rs/SDWebImage/pull/701)
- Ability to save images to cache directly - [#714](https://github.com/rs/SDWebImage/pull/714)
- Support for image orientation - [#764](https://github.com/rs/SDWebImage/pull/764)
- Added async `SDImageCache removeImageForKey:withCompletion:` - [#732](https://github.com/rs/SDWebImage/pull/732) [cd4b925](https://github.com/rs/SDWebImage/commit/cd4b925)
- Exposed cache paths - [#339](https://github.com/rs/SDWebImage/issues/339)
- Exposed `SDWebImageManager cacheKeyForURL:` - [5fd21e5](https://github.com/rs/SDWebImage/commit/5fd21e5)
- Exposing `SDWebImageManager` instance from the `SDWebImagePrefetcher` class - [6c409cd](https://github.com/rs/SDWebImage/commit/6c409cd)
- `SDWebImageManager` uses the shared instance of `SDWebImageDownloader` - [0772019](https://github.com/rs/SDWebImage/commit/0772019)
- Refactor the cancel logic - [#771](https://github.com/rs/SDWebImage/pull/771) [6d01e80](https://github.com/rs/SDWebImage/commit/6d01e80) [23874cd](https://github.com/rs/SDWebImage/commit/23874cd) [a6f11b3](https://github.com/rs/SDWebImage/commit/a6f11b3)
- Added method `SDWebImageManager cachedImageExistsForURL:` to check if an image exists in either the disk OR the memory cache - [#644](https://github.com/rs/SDWebImage/pull/644)
- Added option to use the cached image instead of the placeholder for `UIImageView`. Replaces [#541](https://github.com/rs/SDWebImage/pull/541) - [#599](https://github.com/rs/SDWebImage/issues/599) [30f6726](https://github.com/rs/SDWebImage/commit/30f6726)
- Created workspace + added unit tests target
- Updated documentation - [#476](https://github.com/rs/SDWebImage/issues/476) [#384](https://github.com/rs/SDWebImage/issues/384) [#526](https://github.com/rs/SDWebImage/issues/526) [#376](https://github.com/rs/SDWebImage/pull/376) [a8f5627](https://github.com/rs/SDWebImage/commit/a8f5627)
## Bugfixes
- Fixed Xcode 6 builds - [#741](https://github.com/rs/SDWebImage/pull/741) [0b47342](https://github.com/rs/SDWebImage/commit/0b47342)
- Fixed `diskImageExistsWithKey:` deadlock - [#625](https://github.com/rs/SDWebImage/issues/625) [6e4fbaf](https://github.com/rs/SDWebImage/commit/6e4fbaf)
For consistency, added async methods in `SDWebImageManager` `cachedImageExistsForURL:completion:` and `diskImageExistsForURL:completion:`
- Fixed race condition that causes cancellation of one download operation to stop a run loop that is now used for another download operation. Race is introduced through `performSelector:onThread:withObject:waitUntilDone:` - [#698](https://github.com/rs/SDWebImage/pull/698)
- Fixed race condition between operation cancelation and loading finish - [39db378](https://github.com/rs/SDWebImage/commit/39db378) [#621](https://github.com/rs/SDWebImage/pull/621) [#783](https://github.com/rs/SDWebImage/pull/783)
- Fixed race condition in SDWebImageManager if one operation is cancelled - [f080e38](https://github.com/rs/SDWebImage/commit/f080e38) [#699](https://github.com/rs/SDWebImage/pull/699)
- Fixed issue where cancelled operations aren't removed from `runningOperations` - [#68](https://github.com/rs/SDWebImage/issues/68)
- Should not add url to failedURLs when timeout, cancel and so on - [#766](https://github.com/rs/SDWebImage/pull/766) [#707](https://github.com/rs/SDWebImage/issues/707)
- Fixed potential *object mutated while being enumerated* crash - [#727](https://github.com/rs/SDWebImage/pull/727) [#728](https://github.com/rs/SDWebImage/pull/728) (revert a threading fix from [#727](https://github.com/rs/SDWebImage/pull/727))
- Fixed `NSURLConnection` response statusCode not valid (e.g. 404), downloader never stops its runloop and hangs the operation queue - [#735](https://github.com/rs/SDWebImage/pull/735)
- Fixed `SDWebImageRefreshCached` bug for large images - [#744](https://github.com/rs/SDWebImage/pull/744)
- Added proper handling for `SDWebImageDownloaderLowPriority` - [#713](https://github.com/rs/SDWebImage/issues/713) [#745](https://github.com/rs/SDWebImage/issues/745)
- Fixed fixing potential bug when sending a nil url for UIButton+WebCache - [#761](https://github.com/rs/SDWebImage/issues/761) [#763](https://github.com/rs/SDWebImage/pull/763)
- Fixed issue [#529](https://github.com/rs/SDWebImage/pull/529) - if the `cacheKeyFilter` was set, this was ignored when computing the `scaledImageForKey`. For most of the developers that did not set `cacheKeyFilter`, the code will work exactly the same - [eb91fdd](https://github.com/rs/SDWebImage/commit/eb91fdd)
- Returning error in setImage completedBlock if the url was nil. Added `dispatch_main_async_safe` macro - [#505](https://github.com/rs/SDWebImage/issues/505) [af3e4f8](https://github.com/rs/SDWebImage/commit/af3e4f8)
- Avoid premature completion of prefetcher if request fails - [#751](https://github.com/rs/SDWebImage/pull/751)
- Return nil from `SDScaledImageForKey` if the input image is nil - [#365](https://github.com/rs/SDWebImage/issues/365) [#750](https://github.com/rs/SDWebImage/pull/750)
- Do not load placeholder image if `SDWebImageDelayPlaceholder` option specified - [#780](https://github.com/rs/SDWebImage/pull/780)
- Make sure we call the `startPrefetchingAtIndex:` method from main queue - [#694](https://github.com/rs/SDWebImage/pull/694)
- Save image in cache before calling completion block - [#700](https://github.com/rs/SDWebImage/pull/700)
- Fixed arm64 warnings - [#685](https://github.com/rs/SDWebImage/pull/685) [#720](https://github.com/rs/SDWebImage/pull/720) [#721](https://github.com/rs/SDWebImage/pull/721) [#687](https://github.com/rs/SDWebImage/pull/687)
- Improved logging - [#721](https://github.com/rs/SDWebImage/pull/721)
- Added `SDWebImageCompat.m` to `SDWebImage+MKAnnotation` target
## [3.6 Fix and cleanup on Mar 24th, 2014](https://github.com/rs/SDWebImage/releases/tag/3.6)
## [3.5.4 ARM64 Support on Feb 24th, 2014](https://github.com/rs/SDWebImage/releases/tag/3.5.4)
## [3.5.3 on Jan 7th, 2014](https://github.com/rs/SDWebImage/releases/tag/3.5.3)
## [3.5.2 on Jan 2nd, 2014](https://github.com/rs/SDWebImage/releases/tag/3.5.2)
## [3.5.1 on Dec 3rd, 2013](https://github.com/rs/SDWebImage/releases/tag/3.5.1)
## [3.5 WebP Target, iOS 7, Fixes on Oct 4th, 2013](https://github.com/rs/SDWebImage/releases/tag/3.5)
- Fix iOS 7 related issues
- Move `WebP` support to a dedicated target
- Removed strong reference to `UIImageView` which was causing a crash in the nested block
- Fix timeout issue
- Add some methods that allow to check if an image exists on disk without taking it off disk and decompressing it first
## [3.4 Animated image category, bug fixes on Aug 13th, 2013](https://github.com/rs/SDWebImage/releases/tag/3.4)
- Add `calculateSizeWithCompletionBlock`
- Add multiple download of images for animationImages property of `UIImageView`
- Add background task for disk cleanup [#306](https://github.com/rs/SDWebImage/issues/306)
- Fix dead thread issue on iOS 5 [#444](https://github.com/rs/SDWebImage/pull/444), [#399](https://github.com/rs/SDWebImage/issues/399), [#466](https://github.com/rs/SDWebImage/issues/466)
- Make IO operations cancelable to fix perf issue with heavy images [#462](https://github.com/rs/SDWebImage/issues/462)
- Fix crash `Collection <__NSArrayM: ...> was mutated while being enumerated.` [#471](https://github.com/rs/SDWebImage/pull/471)
## [3.3 WebP, Animated GIF and more on Jun 14th, 2013](https://github.com/rs/SDWebImage/releases/tag/3.3)
- WebP image format support [#410](https://github.com/rs/SDWebImage/issues/410)
- Animated GIF support [#375](https://github.com/rs/SDWebImage/pull/375)
- Custom image cache search paths [#156](https://github.com/rs/SDWebImage/pull/156)
- Bug fixes
## [3.2 Bug fixes on Mar 13th, 2013](https://github.com/rs/SDWebImage/releases/tag/3.2)
- `SDWebImageRefreshCached` download option [#326](https://github.com/rs/SDWebImage/pull/326)
- New `SDWebImageManager` delegate methods [ebd63a88c1](https://github.com/rs/SDWebImage/commit/ebd63a88c116ac7acfbeded5c84d0fffa2443438)
- Fix long standing issue with alpha en JPEGs [#299](https://github.com/rs/SDWebImage/pull/299)
- Add synchronous disk-cache loading method [#297](https://github.com/rs/SDWebImage/pull/297)
- Fix `SDWebImageCacheMemoryOnly` flag
- Bug fixes
## [3.1 Bug fixes on Jan 21st, 2013](https://github.com/rs/SDWebImage/releases/tag/3.1)
## [3.0 Complete rewrite on Nov 29th, 2012](https://github.com/rs/SDWebImage/releases/tag/3.0)
- Complete rewrite of the library using `GCD`, `ARC`, `NSCache` and blocks
- Drop compatibility with iOS 3 and 4
## [2.7.4 Bug fixes on Nov 14th, 2012](https://github.com/rs/SDWebImage/releases/tag/2.7.4)
## [2.7.3 on Nov 3rd, 2012](https://github.com/rs/SDWebImage/releases/tag/2.7.3)
## [2.7.2 on Oct 23rd, 2012](https://github.com/rs/SDWebImage/releases/tag/2.7.2)
## [2.7.1 on Oct 19th, 2012](https://github.com/rs/SDWebImage/releases/tag/2.7.1)
## [2.7 on Sep 8th, 2012](https://github.com/rs/SDWebImage/releases/tag/2.7)
## [2.6 on May 4th, 2012](https://github.com/rs/SDWebImage/releases/tag/2.6)
## [2.5 on Mar 22nd, 2012](https://github.com/rs/SDWebImage/releases/tag/2.5)
## [2.4 on Oct 1st, 2011](https://github.com/rs/SDWebImage/releases/tag/2.4)
## [2.3 on Sep 16th, 2010](https://github.com/rs/SDWebImage/releases/tag/2.3)
## [2.2 on Aug 29th, 2010](https://github.com/rs/SDWebImage/releases/tag/2.2)
## [2.1.0 on Jun 12th, 2010](https://github.com/rs/SDWebImage/releases/tag/2.1.0)
## [2.1 on Jun 12th, 2010](https://github.com/rs/SDWebImage/releases/tag/2.1)
## [2.0.0 on Jun 9th, 2010](https://github.com/rs/SDWebImage/releases/tag/2.0.0)
## [2.0 on Jun 9th, 2010](https://github.com/rs/SDWebImage/releases/tag/2.0)
## [1.0.0 on Dec 31st, 2009](https://github.com/rs/SDWebImage/releases/tag/1.0.0)
## [1.0 on Dec 31st, 2009](https://github.com/rs/SDWebImage/releases/tag/1.0)

View File

@ -8,6 +8,8 @@
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
3E75A9861742DBE700DA412D /* CustomPathImages in Resources */ = {isa = PBXBuildFile; fileRef = 3E75A9851742DBE700DA412D /* CustomPathImages */; }; 3E75A9861742DBE700DA412D /* CustomPathImages in Resources */ = {isa = PBXBuildFile; fileRef = 3E75A9851742DBE700DA412D /* CustomPathImages */; };
4389D77A1B5463BA009F647B /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4389D7791B5463BA009F647B /* QuartzCore.framework */; };
4389D77C1B5463CA009F647B /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4389D77B1B5463CA009F647B /* MobileCoreServices.framework */; };
531041C1157EAC8F00BBABC3 /* ImageIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 537612E6155ABA44005750A4 /* ImageIO.framework */; }; 531041C1157EAC8F00BBABC3 /* ImageIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 537612E6155ABA44005750A4 /* ImageIO.framework */; };
5376129A155AB74D005750A4 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 53761299155AB74D005750A4 /* UIKit.framework */; }; 5376129A155AB74D005750A4 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 53761299155AB74D005750A4 /* UIKit.framework */; };
5376129C155AB74D005750A4 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5376129B155AB74D005750A4 /* Foundation.framework */; }; 5376129C155AB74D005750A4 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5376129B155AB74D005750A4 /* Foundation.framework */; };
@ -22,23 +24,25 @@
53A2B50E155B155A00B12423 /* placeholder@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 53A2B50C155B155A00B12423 /* placeholder@2x.png */; }; 53A2B50E155B155A00B12423 /* placeholder@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 53A2B50C155B155A00B12423 /* placeholder@2x.png */; };
53EEC18916484553007601E1 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 53EEC18816484553007601E1 /* Default-568h@2x.png */; }; 53EEC18916484553007601E1 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 53EEC18816484553007601E1 /* Default-568h@2x.png */; };
DA248D44195470FD00390AB0 /* MapKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 537612E3155ABA3C005750A4 /* MapKit.framework */; }; DA248D44195470FD00390AB0 /* MapKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 537612E3155ABA3C005750A4 /* MapKit.framework */; };
DA248D79195484A500390AB0 /* libSDWebImage+WebP.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DA248D761954841D00390AB0 /* libSDWebImage+WebP.a */; }; DA4D3C6F1B55303A00EC8389 /* libSDWebImage+All.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DA4D3C6E1B55303500EC8389 /* libSDWebImage+All.a */; };
DAE75CB41B5532350044DE5E /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DAE75CB31B5532350044DE5E /* SystemConfiguration.framework */; };
DAE75CB61B5532640044DE5E /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DAE75CB51B5532640044DE5E /* Security.framework */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */ /* Begin PBXContainerItemProxy section */
43A0FAAE1BDD16AC00B7582B /* PBXContainerItemProxy */ = { 4389D7741B546365009F647B /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy; isa = PBXContainerItemProxy;
containerPortal = DA248D6C1954841D00390AB0 /* SDWebImage.xcodeproj */; containerPortal = DA248D6C1954841D00390AB0 /* SDWebImage.xcodeproj */;
proxyType = 2; proxyType = 2;
remoteGlobalIDString = 4A2CADFF1AB4BB5300B6BC39; remoteGlobalIDString = 4A2CADFF1AB4BB5300B6BC39;
remoteInfo = WebImage; remoteInfo = WebImage;
}; };
43AEAFA91D008FEE005B41A8 /* PBXContainerItemProxy */ = { 4389D7761B546365009F647B /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy; isa = PBXContainerItemProxy;
containerPortal = DA248D6C1954841D00390AB0 /* SDWebImage.xcodeproj */; containerPortal = DA248D6C1954841D00390AB0 /* SDWebImage.xcodeproj */;
proxyType = 2; proxyType = 2;
remoteGlobalIDString = 00733A4C1BC487C000A5A117; remoteGlobalIDString = 4389D7641B545EE0009F647B;
remoteInfo = "WebImage tvOS"; remoteInfo = "SDWebImage+GIF";
}; };
DA248D731954841D00390AB0 /* PBXContainerItemProxy */ = { DA248D731954841D00390AB0 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy; isa = PBXContainerItemProxy;
@ -61,10 +65,26 @@
remoteGlobalIDString = 531041E0157EAFA400BBABC3; remoteGlobalIDString = 531041E0157EAFA400BBABC3;
remoteInfo = "SDWebImage+MKAnnotation"; remoteInfo = "SDWebImage+MKAnnotation";
}; };
DA4D3C6D1B55303500EC8389 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = DA248D6C1954841D00390AB0 /* SDWebImage.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = DA4D3C1B1B552F4100EC8389;
remoteInfo = "SDWebImage+All";
};
DAE75C211B55307F0044DE5E /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = DA248D6C1954841D00390AB0 /* SDWebImage.xcodeproj */;
proxyType = 1;
remoteGlobalIDString = DA4D3BEF1B552F4100EC8389;
remoteInfo = "SDWebImage+All";
};
/* End PBXContainerItemProxy section */ /* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
3E75A9851742DBE700DA412D /* CustomPathImages */ = {isa = PBXFileReference; lastKnownFileType = folder; path = CustomPathImages; sourceTree = SOURCE_ROOT; }; 3E75A9851742DBE700DA412D /* CustomPathImages */ = {isa = PBXFileReference; lastKnownFileType = folder; path = CustomPathImages; sourceTree = SOURCE_ROOT; };
4389D7791B5463BA009F647B /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
4389D77B1B5463CA009F647B /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; };
53761295155AB74D005750A4 /* SDWebImage Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "SDWebImage Demo.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 53761295155AB74D005750A4 /* SDWebImage Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "SDWebImage Demo.app"; sourceTree = BUILT_PRODUCTS_DIR; };
53761299155AB74D005750A4 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 53761299155AB74D005750A4 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
5376129B155AB74D005750A4 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 5376129B155AB74D005750A4 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
@ -86,6 +106,8 @@
53A2B50C155B155A00B12423 /* placeholder@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "placeholder@2x.png"; sourceTree = "<group>"; }; 53A2B50C155B155A00B12423 /* placeholder@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "placeholder@2x.png"; sourceTree = "<group>"; };
53EEC18816484553007601E1 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Default-568h@2x.png"; path = "../Default-568h@2x.png"; sourceTree = "<group>"; }; 53EEC18816484553007601E1 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Default-568h@2x.png"; path = "../Default-568h@2x.png"; sourceTree = "<group>"; };
DA248D6C1954841D00390AB0 /* SDWebImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = SDWebImage.xcodeproj; path = ../SDWebImage.xcodeproj; sourceTree = "<group>"; }; DA248D6C1954841D00390AB0 /* SDWebImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = SDWebImage.xcodeproj; path = ../SDWebImage.xcodeproj; sourceTree = "<group>"; };
DAE75CB31B5532350044DE5E /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
DAE75CB51B5532640044DE5E /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
@ -93,7 +115,11 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
DA248D79195484A500390AB0 /* libSDWebImage+WebP.a in Frameworks */, DA4D3C6F1B55303A00EC8389 /* libSDWebImage+All.a in Frameworks */,
DAE75CB61B5532640044DE5E /* Security.framework in Frameworks */,
DAE75CB41B5532350044DE5E /* SystemConfiguration.framework in Frameworks */,
4389D77C1B5463CA009F647B /* MobileCoreServices.framework in Frameworks */,
4389D77A1B5463BA009F647B /* QuartzCore.framework in Frameworks */,
DA248D44195470FD00390AB0 /* MapKit.framework in Frameworks */, DA248D44195470FD00390AB0 /* MapKit.framework in Frameworks */,
531041C1157EAC8F00BBABC3 /* ImageIO.framework in Frameworks */, 531041C1157EAC8F00BBABC3 /* ImageIO.framework in Frameworks */,
5376129A155AB74D005750A4 /* UIKit.framework in Frameworks */, 5376129A155AB74D005750A4 /* UIKit.framework in Frameworks */,
@ -126,6 +152,10 @@
53761298155AB74D005750A4 /* Frameworks */ = { 53761298155AB74D005750A4 /* Frameworks */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
DAE75CB51B5532640044DE5E /* Security.framework */,
DAE75CB31B5532350044DE5E /* SystemConfiguration.framework */,
4389D77B1B5463CA009F647B /* MobileCoreServices.framework */,
4389D7791B5463BA009F647B /* QuartzCore.framework */,
537612E6155ABA44005750A4 /* ImageIO.framework */, 537612E6155ABA44005750A4 /* ImageIO.framework */,
537612E3155ABA3C005750A4 /* MapKit.framework */, 537612E3155ABA3C005750A4 /* MapKit.framework */,
53761299155AB74D005750A4 /* UIKit.framework */, 53761299155AB74D005750A4 /* UIKit.framework */,
@ -170,9 +200,10 @@
children = ( children = (
DA248D741954841D00390AB0 /* libSDWebImage.a */, DA248D741954841D00390AB0 /* libSDWebImage.a */,
DA248D761954841D00390AB0 /* libSDWebImage+WebP.a */, DA248D761954841D00390AB0 /* libSDWebImage+WebP.a */,
4389D7771B546365009F647B /* libSDWebImage+GIF.a */,
DA248D781954841D00390AB0 /* libSDWebImage+MKAnnotation.a */, DA248D781954841D00390AB0 /* libSDWebImage+MKAnnotation.a */,
43A0FAAF1BDD16AC00B7582B /* WebImage.framework */, 4389D7751B546365009F647B /* WebImage.framework */,
43AEAFAA1D008FEE005B41A8 /* WebImage.framework */, DA4D3C6E1B55303500EC8389 /* libSDWebImage+All.a */,
); );
name = Products; name = Products;
sourceTree = "<group>"; sourceTree = "<group>";
@ -191,6 +222,7 @@
buildRules = ( buildRules = (
); );
dependencies = ( dependencies = (
DAE75C221B55307F0044DE5E /* PBXTargetDependency */,
); );
name = "SDWebImage Demo"; name = "SDWebImage Demo";
productName = "SDWebImage Demo"; productName = "SDWebImage Demo";
@ -203,7 +235,7 @@
5376128C155AB74D005750A4 /* Project object */ = { 5376128C155AB74D005750A4 /* Project object */ = {
isa = PBXProject; isa = PBXProject;
attributes = { attributes = {
LastUpgradeCheck = 0710; LastUpgradeCheck = 0500;
ORGANIZATIONNAME = Dailymotion; ORGANIZATIONNAME = Dailymotion;
}; };
buildConfigurationList = 5376128F155AB74D005750A4 /* Build configuration list for PBXProject "SDWebImage Demo" */; buildConfigurationList = 5376128F155AB74D005750A4 /* Build configuration list for PBXProject "SDWebImage Demo" */;
@ -230,18 +262,18 @@
/* End PBXProject section */ /* End PBXProject section */
/* Begin PBXReferenceProxy section */ /* Begin PBXReferenceProxy section */
43A0FAAF1BDD16AC00B7582B /* WebImage.framework */ = { 4389D7751B546365009F647B /* WebImage.framework */ = {
isa = PBXReferenceProxy; isa = PBXReferenceProxy;
fileType = wrapper.framework; fileType = wrapper.framework;
path = WebImage.framework; path = WebImage.framework;
remoteRef = 43A0FAAE1BDD16AC00B7582B /* PBXContainerItemProxy */; remoteRef = 4389D7741B546365009F647B /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR; sourceTree = BUILT_PRODUCTS_DIR;
}; };
43AEAFAA1D008FEE005B41A8 /* WebImage.framework */ = { 4389D7771B546365009F647B /* libSDWebImage+GIF.a */ = {
isa = PBXReferenceProxy; isa = PBXReferenceProxy;
fileType = wrapper.framework; fileType = archive.ar;
path = WebImage.framework; path = "libSDWebImage+GIF.a";
remoteRef = 43AEAFA91D008FEE005B41A8 /* PBXContainerItemProxy */; remoteRef = 4389D7761B546365009F647B /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR; sourceTree = BUILT_PRODUCTS_DIR;
}; };
DA248D741954841D00390AB0 /* libSDWebImage.a */ = { DA248D741954841D00390AB0 /* libSDWebImage.a */ = {
@ -265,6 +297,13 @@
remoteRef = DA248D771954841D00390AB0 /* PBXContainerItemProxy */; remoteRef = DA248D771954841D00390AB0 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR; sourceTree = BUILT_PRODUCTS_DIR;
}; };
DA4D3C6E1B55303500EC8389 /* libSDWebImage+All.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = "libSDWebImage+All.a";
remoteRef = DA4D3C6D1B55303500EC8389 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
/* End PBXReferenceProxy section */ /* End PBXReferenceProxy section */
/* Begin PBXResourcesBuildPhase section */ /* Begin PBXResourcesBuildPhase section */
@ -297,6 +336,14 @@
}; };
/* End PBXSourcesBuildPhase section */ /* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
DAE75C221B55307F0044DE5E /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
name = "SDWebImage+All";
targetProxy = DAE75C211B55307F0044DE5E /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */ /* Begin PBXVariantGroup section */
537612B1155AB74D005750A4 /* MasterViewController.xib */ = { 537612B1155AB74D005750A4 /* MasterViewController.xib */ = {
isa = PBXVariantGroup; isa = PBXVariantGroup;
@ -324,7 +371,6 @@
CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_ARC = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = "compiler-default"; GCC_C_LANGUAGE_STANDARD = "compiler-default";
GCC_DYNAMIC_NO_PIC = NO; GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0; GCC_OPTIMIZATION_LEVEL = 0;
@ -337,7 +383,7 @@
GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 7.0; IPHONEOS_DEPLOYMENT_TARGET = 5.0;
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos; SDKROOT = iphoneos;
}; };
@ -355,7 +401,7 @@
GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 7.0; IPHONEOS_DEPLOYMENT_TARGET = 5.0;
OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1";
SDKROOT = iphoneos; SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES; VALIDATE_PRODUCT = YES;
@ -379,7 +425,6 @@
INFOPLIST_FILE = "SDWebImage Demo/SDWebImage Demo-Info.plist"; INFOPLIST_FILE = "SDWebImage Demo/SDWebImage Demo-Info.plist";
OTHER_CFLAGS = ""; OTHER_CFLAGS = "";
OTHER_LDFLAGS = "-ObjC"; OTHER_LDFLAGS = "-ObjC";
PRODUCT_BUNDLE_IDENTIFIER = "com.dailymotion.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app; WRAPPER_EXTENSION = app;
}; };
@ -401,7 +446,6 @@
); );
INFOPLIST_FILE = "SDWebImage Demo/SDWebImage Demo-Info.plist"; INFOPLIST_FILE = "SDWebImage Demo/SDWebImage Demo-Info.plist";
OTHER_LDFLAGS = "-ObjC"; OTHER_LDFLAGS = "-ObjC";
PRODUCT_BUNDLE_IDENTIFIER = "com.dailymotion.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app; WRAPPER_EXTENSION = app;
}; };

View File

@ -11,7 +11,7 @@
#import "DetailViewController.h" #import "DetailViewController.h"
@interface MasterViewController () { @interface MasterViewController () {
NSMutableArray *_objects; NSArray *_objects;
} }
@end @end
@ -35,17 +35,312 @@
[SDWebImageManager sharedManager].imageDownloader.username = @"httpwatch"; [SDWebImageManager sharedManager].imageDownloader.username = @"httpwatch";
[SDWebImageManager sharedManager].imageDownloader.password = @"httpwatch01"; [SDWebImageManager sharedManager].imageDownloader.password = @"httpwatch01";
_objects = [NSMutableArray arrayWithObjects: _objects = [NSArray arrayWithObjects:
@"http://www.httpwatch.com/httpgallery/authentication/authenticatedimage/default.aspx?0.35786508303135633", // requires HTTP auth, used to demo the NTLM auth @"http://www.httpwatch.com/httpgallery/authentication/authenticatedimage/default.aspx?0.35786508303135633", // requires HTTP auth, used to demo the NTLM auth
@"https://raw.githubusercontent.com/liyong03/YLGIFImage/master/YLGIFImageDemo/YLGIFImageDemo/joy.gif",
@"http://assets.sbnation.com/assets/2512203/dogflops.gif", @"http://assets.sbnation.com/assets/2512203/dogflops.gif",
@"http://www.ioncannon.net/wp-content/uploads/2011/06/test2.webp", @"http://www.ioncannon.net/wp-content/uploads/2011/06/test2.webp",
@"http://www.ioncannon.net/wp-content/uploads/2011/06/test9.webp", @"http://www.ioncannon.net/wp-content/uploads/2011/06/test9.webp",
@"http://static2.dmcdn.net/static/video/656/177/44771656:jpeg_preview_small.jpg?20120509154705",
@"http://static2.dmcdn.net/static/video/629/228/44822926:jpeg_preview_small.jpg?20120509181018",
@"http://static2.dmcdn.net/static/video/116/367/44763611:jpeg_preview_small.jpg?20120509101749",
@"http://static2.dmcdn.net/static/video/340/086/44680043:jpeg_preview_small.jpg?20120509180118",
@"http://static2.dmcdn.net/static/video/666/645/43546666:jpeg_preview_small.jpg?20120412153140",
@"http://static2.dmcdn.net/static/video/771/577/44775177:jpeg_preview_small.jpg?20120509183230",
@"http://static2.dmcdn.net/static/video/810/508/44805018:jpeg_preview_small.jpg?20120508125339",
@"http://static2.dmcdn.net/static/video/152/008/44800251:jpeg_preview_small.jpg?20120508103336",
@"http://static2.dmcdn.net/static/video/694/741/35147496:jpeg_preview_small.jpg?20120508111445",
@"http://static2.dmcdn.net/static/video/988/667/44766889:jpeg_preview_small.jpg?20120508130425",
@"http://static2.dmcdn.net/static/video/282/467/44764282:jpeg_preview_small.jpg?20120507130637",
@"http://static2.dmcdn.net/static/video/754/657/44756457:jpeg_preview_small.jpg?20120507093012",
@"http://static2.dmcdn.net/static/video/831/107/44701138:jpeg_preview_small.jpg?20120506133917",
@"http://static2.dmcdn.net/static/video/411/057/44750114:jpeg_preview_small.jpg?20120507014914",
@"http://static2.dmcdn.net/static/video/894/547/44745498:jpeg_preview_small.jpg?20120509183004",
@"http://static2.dmcdn.net/static/video/082/947/44749280:jpeg_preview_small.jpg?20120507015022",
@"http://static2.dmcdn.net/static/video/833/347/44743338:jpeg_preview_small.jpg?20120509183004",
@"http://static2.dmcdn.net/static/video/683/666/44666386:jpeg_preview_small.jpg?20120505111208",
@"http://static2.dmcdn.net/static/video/595/946/44649595:jpeg_preview_small.jpg?20120507194104",
@"http://static2.dmcdn.net/static/video/984/935/44539489:jpeg_preview_small.jpg?20120501184650",
@"http://static2.dmcdn.net/static/video/440/416/44614044:jpeg_preview_small.jpg?20120505174152",
@"http://static2.dmcdn.net/static/video/561/977/20779165:jpeg_preview_small.jpg?20120423161805",
@"http://static2.dmcdn.net/static/video/104/546/44645401:jpeg_preview_small.jpg?20120507185246",
@"http://static2.dmcdn.net/static/video/671/636/44636176:jpeg_preview_small.jpg?20120504021339",
@"http://static2.dmcdn.net/static/video/142/746/44647241:jpeg_preview_small.jpg?20120504104451",
@"http://static2.dmcdn.net/static/video/776/860/44068677:jpeg_preview_small.jpg?20120507185251",
@"http://static2.dmcdn.net/static/video/026/626/44626620:jpeg_preview_small.jpg?20120503203036",
@"http://static2.dmcdn.net/static/video/364/663/39366463:jpeg_preview_small.jpg?20120509163505",
@"http://static2.dmcdn.net/static/video/392/895/44598293:jpeg_preview_small.jpg?20120503165252",
@"http://static2.dmcdn.net/static/video/620/865/44568026:jpeg_preview_small.jpg?20120507185121",
@"http://static2.dmcdn.net/static/video/031/395/44593130:jpeg_preview_small.jpg?20120507185139",
@"http://static2.dmcdn.net/static/video/676/495/44594676:jpeg_preview_small.jpg?20120503121341",
@"http://static2.dmcdn.net/static/video/025/195/44591520:jpeg_preview_small.jpg?20120503132132",
@"http://static2.dmcdn.net/static/video/993/665/44566399:jpeg_preview_small.jpg?20120503182623",
@"http://static2.dmcdn.net/static/video/137/635/44536731:jpeg_preview_small.jpg?20120501165940",
@"http://static2.dmcdn.net/static/video/611/794/44497116:jpeg_preview_small.jpg?20120507184954",
@"http://static2.dmcdn.net/static/video/732/790/44097237:jpeg_preview_small.jpg?20120430162348",
@"http://static2.dmcdn.net/static/video/064/991/44199460:jpeg_preview_small.jpg?20120430101250",
@"http://static2.dmcdn.net/static/video/404/094/44490404:jpeg_preview_small.jpg?20120507184948",
@"http://static2.dmcdn.net/static/video/413/120/44021314:jpeg_preview_small.jpg?20120507180850",
@"http://static2.dmcdn.net/static/video/200/584/44485002:jpeg_preview_small.jpg?20120507184941",
@"http://static2.dmcdn.net/static/video/551/318/42813155:jpeg_preview_small.jpg?20120412153202",
@"http://static2.dmcdn.net/static/video/524/750/44057425:jpeg_preview_small.jpg?20120501220912",
@"http://static2.dmcdn.net/static/video/124/843/44348421:jpeg_preview_small.jpg?20120507184551",
@"http://static2.dmcdn.net/static/video/496/394/42493694:jpeg_preview_small.jpg?20120430105337",
@"http://static2.dmcdn.net/static/video/548/883/44388845:jpeg_preview_small.jpg?20120428212713",
@"http://static2.dmcdn.net/static/video/282/533/44335282:jpeg_preview_small.jpg?20120427102844",
@"http://static2.dmcdn.net/static/video/257/132/44231752:jpeg_preview_small.jpg?20120428212609",
@"http://static2.dmcdn.net/static/video/480/193/44391084:jpeg_preview_small.jpg?20120501143214",
@"http://static2.dmcdn.net/static/video/903/432/44234309:jpeg_preview_small.jpg?20120427200002",
@"http://static2.dmcdn.net/static/video/646/573/44375646:jpeg_preview_small.jpg?20120507184652",
@"http://static2.dmcdn.net/static/video/709/573/44375907:jpeg_preview_small.jpg?20120507184652",
@"http://static2.dmcdn.net/static/video/885/633/44336588:jpeg_preview_small.jpg?20120507184540",
@"http://static2.dmcdn.net/static/video/732/523/44325237:jpeg_preview_small.jpg?20120426110308",
@"http://static2.dmcdn.net/static/video/935/132/44231539:jpeg_preview_small.jpg?20120426115744",
@"http://static2.dmcdn.net/static/video/941/129/43921149:jpeg_preview_small.jpg?20120426094640",
@"http://static2.dmcdn.net/static/video/775/942/44249577:jpeg_preview_small.jpg?20120425011228",
@"http://static2.dmcdn.net/static/video/868/332/44233868:jpeg_preview_small.jpg?20120429152901",
@"http://static2.dmcdn.net/static/video/959/732/44237959:jpeg_preview_small.jpg?20120425133534",
@"http://static2.dmcdn.net/static/video/383/402/44204383:jpeg_preview_small.jpg?20120424185842",
@"http://static2.dmcdn.net/static/video/971/932/44239179:jpeg_preview_small.jpg?20120424154419",
@"http://static2.dmcdn.net/static/video/096/991/44199690:jpeg_preview_small.jpg?20120423162001",
@"http://static2.dmcdn.net/static/video/661/450/44054166:jpeg_preview_small.jpg?20120507180921",
@"http://static2.dmcdn.net/static/video/419/322/44223914:jpeg_preview_small.jpg?20120424112858",
@"http://static2.dmcdn.net/static/video/673/391/44193376:jpeg_preview_small.jpg?20120507181450",
@"http://static2.dmcdn.net/static/video/907/781/44187709:jpeg_preview_small.jpg?20120423103507",
@"http://static2.dmcdn.net/static/video/446/571/44175644:jpeg_preview_small.jpg?20120423033122",
@"http://static2.dmcdn.net/static/video/146/671/44176641:jpeg_preview_small.jpg?20120428235503",
@"http://static2.dmcdn.net/static/video/463/571/44175364:jpeg_preview_small.jpg?20120428235503",
@"http://static2.dmcdn.net/static/video/442/471/44174244:jpeg_preview_small.jpg?20120428235502",
@"http://static2.dmcdn.net/static/video/523/471/44174325:jpeg_preview_small.jpg?20120422205107",
@"http://static2.dmcdn.net/static/video/977/159/43951779:jpeg_preview_small.jpg?20120420182100",
@"http://static2.dmcdn.net/static/video/875/880/40088578:jpeg_preview_small.jpg?20120501131026",
@"http://static2.dmcdn.net/static/video/434/992/38299434:jpeg_preview_small.jpg?20120503193356",
@"http://static2.dmcdn.net/static/video/448/798/42897844:jpeg_preview_small.jpg?20120418155203",
@"http://static2.dmcdn.net/static/video/374/690/44096473:jpeg_preview_small.jpg?20120507181124",
@"http://static2.dmcdn.net/static/video/284/313/43313482:jpeg_preview_small.jpg?20120420184511",
@"http://static2.dmcdn.net/static/video/682/060/44060286:jpeg_preview_small.jpg?20120421122436",
@"http://static2.dmcdn.net/static/video/701/750/44057107:jpeg_preview_small.jpg?20120420112918",
@"http://static2.dmcdn.net/static/video/790/850/44058097:jpeg_preview_small.jpg?20120424114522",
@"http://static2.dmcdn.net/static/video/153/617/43716351:jpeg_preview_small.jpg?20120419190650",
@"http://static2.dmcdn.net/static/video/394/633/37336493:jpeg_preview_small.jpg?20111109151109",
@"http://static2.dmcdn.net/static/video/893/330/44033398:jpeg_preview_small.jpg?20120419123322",
@"http://static2.dmcdn.net/static/video/395/046/42640593:jpeg_preview_small.jpg?20120418103546",
@"http://static2.dmcdn.net/static/video/913/040/44040319:jpeg_preview_small.jpg?20120419164908",
@"http://static2.dmcdn.net/static/video/090/020/44020090:jpeg_preview_small.jpg?20120418185934",
@"http://static2.dmcdn.net/static/video/349/299/43992943:jpeg_preview_small.jpg?20120418112749",
@"http://static2.dmcdn.net/static/video/530/189/43981035:jpeg_preview_small.jpg?20120419013834",
@"http://static2.dmcdn.net/static/video/763/469/43964367:jpeg_preview_small.jpg?20120425111931",
@"http://static2.dmcdn.net/static/video/961/455/43554169:jpeg_preview_small.jpg?20120418110127",
@"http://static2.dmcdn.net/static/video/666/889/43988666:jpeg_preview_small.jpg?20120507180735",
@"http://static2.dmcdn.net/static/video/160/459/43954061:jpeg_preview_small.jpg?20120501202847",
@"http://static2.dmcdn.net/static/video/352/069/43960253:jpeg_preview_small.jpg?20120503175747",
@"http://static2.dmcdn.net/static/video/096/502/43205690:jpeg_preview_small.jpg?20120417142655",
@"http://static2.dmcdn.net/static/video/257/119/43911752:jpeg_preview_small.jpg?20120416101238",
@"http://static2.dmcdn.net/static/video/874/098/43890478:jpeg_preview_small.jpg?20120415193608",
@"http://static2.dmcdn.net/static/video/406/148/43841604:jpeg_preview_small.jpg?20120416123145",
@"http://static2.dmcdn.net/static/video/463/885/43588364:jpeg_preview_small.jpg?20120409130206",
@"http://static2.dmcdn.net/static/video/176/845/38548671:jpeg_preview_small.jpg?20120414200742",
@"http://static2.dmcdn.net/static/video/447/848/51848744:jpeg_preview_small.jpg?20121105223446",
@"http://static2.dmcdn.net/static/video/337/848/51848733:jpeg_preview_small.jpg?20121105223433",
@"http://static2.dmcdn.net/static/video/707/848/51848707:jpeg_preview_small.jpg?20121105223428",
@"http://static2.dmcdn.net/static/video/102/848/51848201:jpeg_preview_small.jpg?20121105223411",
@"http://static2.dmcdn.net/static/video/817/848/51848718:jpeg_preview_small.jpg?20121105223402",
@"http://static2.dmcdn.net/static/video/007/848/51848700:jpeg_preview_small.jpg?20121105223345",
@"http://static2.dmcdn.net/static/video/696/848/51848696:jpeg_preview_small.jpg?20121105223355",
@"http://static2.dmcdn.net/static/video/296/848/51848692:jpeg_preview_small.jpg?20121105223337",
@"http://static2.dmcdn.net/static/video/080/848/51848080:jpeg_preview_small.jpg?20121105223653",
@"http://static2.dmcdn.net/static/video/386/848/51848683:jpeg_preview_small.jpg?20121105223343",
@"http://static2.dmcdn.net/static/video/876/848/51848678:jpeg_preview_small.jpg?20121105223301",
@"http://static2.dmcdn.net/static/video/866/848/51848668:jpeg_preview_small.jpg?20121105223244",
@"http://static2.dmcdn.net/static/video/572/548/51845275:jpeg_preview_small.jpg?20121105223229",
@"http://static2.dmcdn.net/static/video/972/548/51845279:jpeg_preview_small.jpg?20121105223227",
@"http://static2.dmcdn.net/static/video/112/548/51845211:jpeg_preview_small.jpg?20121105223226",
@"http://static2.dmcdn.net/static/video/549/448/51844945:jpeg_preview_small.jpg?20121105223223",
@"http://static2.dmcdn.net/static/video/166/848/51848661:jpeg_preview_small.jpg?20121105223228",
@"http://static2.dmcdn.net/static/video/856/848/51848658:jpeg_preview_small.jpg?20121105223223",
@"http://static2.dmcdn.net/static/video/746/848/51848647:jpeg_preview_small.jpg?20121105223204",
@"http://static2.dmcdn.net/static/video/446/848/51848644:jpeg_preview_small.jpg?20121105223204",
@"http://static2.dmcdn.net/static/video/726/848/51848627:jpeg_preview_small.jpg?20121105223221",
@"http://static2.dmcdn.net/static/video/436/848/51848634:jpeg_preview_small.jpg?20121105223445",
@"http://static2.dmcdn.net/static/video/836/848/51848638:jpeg_preview_small.jpg?20121105223144",
@"http://static2.dmcdn.net/static/video/036/848/51848630:jpeg_preview_small.jpg?20121105223125",
@"http://static2.dmcdn.net/static/video/026/848/51848620:jpeg_preview_small.jpg?20121105223102",
@"http://static2.dmcdn.net/static/video/895/848/51848598:jpeg_preview_small.jpg?20121105223112",
@"http://static2.dmcdn.net/static/video/116/848/51848611:jpeg_preview_small.jpg?20121105223052",
@"http://static2.dmcdn.net/static/video/006/848/51848600:jpeg_preview_small.jpg?20121105223043",
@"http://static2.dmcdn.net/static/video/432/548/51845234:jpeg_preview_small.jpg?20121105223022",
@"http://static2.dmcdn.net/static/video/785/848/51848587:jpeg_preview_small.jpg?20121105223031",
@"http://static2.dmcdn.net/static/video/975/848/51848579:jpeg_preview_small.jpg?20121105223012",
@"http://static2.dmcdn.net/static/video/965/848/51848569:jpeg_preview_small.jpg?20121105222952",
@"http://static2.dmcdn.net/static/video/365/848/51848563:jpeg_preview_small.jpg?20121105222943",
@"http://static2.dmcdn.net/static/video/755/848/51848557:jpeg_preview_small.jpg?20121105222943",
@"http://static2.dmcdn.net/static/video/722/248/51842227:jpeg_preview_small.jpg?20121105222908",
@"http://static2.dmcdn.net/static/video/155/848/51848551:jpeg_preview_small.jpg?20121105222913",
@"http://static2.dmcdn.net/static/video/345/848/51848543:jpeg_preview_small.jpg?20121105222907",
@"http://static2.dmcdn.net/static/video/535/848/51848535:jpeg_preview_small.jpg?20121105222848",
@"http://static2.dmcdn.net/static/video/035/848/51848530:jpeg_preview_small.jpg?20121105222837",
@"http://static2.dmcdn.net/static/video/525/848/51848525:jpeg_preview_small.jpg?20121105222826",
@"http://static2.dmcdn.net/static/video/233/848/51848332:jpeg_preview_small.jpg?20121105223414",
@"http://static2.dmcdn.net/static/video/125/848/51848521:jpeg_preview_small.jpg?20121105222809",
@"http://static2.dmcdn.net/static/video/005/848/51848500:jpeg_preview_small.jpg?20121105222802",
@"http://static2.dmcdn.net/static/video/015/848/51848510:jpeg_preview_small.jpg?20121105222755",
@"http://static2.dmcdn.net/static/video/121/548/51845121:jpeg_preview_small.jpg?20121105222850",
@"http://static2.dmcdn.net/static/video/205/848/51848502:jpeg_preview_small.jpg?20121105222737",
@"http://static2.dmcdn.net/static/video/697/448/51844796:jpeg_preview_small.jpg?20121105222818",
@"http://static2.dmcdn.net/static/video/494/848/51848494:jpeg_preview_small.jpg?20121105222724",
@"http://static2.dmcdn.net/static/video/806/448/51844608:jpeg_preview_small.jpg?20121105222811",
@"http://static2.dmcdn.net/static/video/729/348/51843927:jpeg_preview_small.jpg?20121105222805",
@"http://static2.dmcdn.net/static/video/865/148/51841568:jpeg_preview_small.jpg?20121105222803",
@"http://static2.dmcdn.net/static/video/481/548/51845184:jpeg_preview_small.jpg?20121105222700",
@"http://static2.dmcdn.net/static/video/190/548/51845091:jpeg_preview_small.jpg?20121105222656",
@"http://static2.dmcdn.net/static/video/128/448/51844821:jpeg_preview_small.jpg?20121105222656",
@"http://static2.dmcdn.net/static/video/784/848/51848487:jpeg_preview_small.jpg?20121105222704",
@"http://static2.dmcdn.net/static/video/182/448/51844281:jpeg_preview_small.jpg?20121105222652",
@"http://static2.dmcdn.net/static/video/801/848/51848108:jpeg_preview_small.jpg?20121105222907",
@"http://static2.dmcdn.net/static/video/974/848/51848479:jpeg_preview_small.jpg?20121105222657",
@"http://static2.dmcdn.net/static/video/274/848/51848472:jpeg_preview_small.jpg?20121105222644",
@"http://static2.dmcdn.net/static/video/954/848/51848459:jpeg_preview_small.jpg?20121105222637",
@"http://static2.dmcdn.net/static/video/554/848/51848455:jpeg_preview_small.jpg?20121105222615",
@"http://static2.dmcdn.net/static/video/944/848/51848449:jpeg_preview_small.jpg?20121105222558",
@"http://static2.dmcdn.net/static/video/144/848/51848441:jpeg_preview_small.jpg?20121105222556",
@"http://static2.dmcdn.net/static/video/134/848/51848431:jpeg_preview_small.jpg?20121105222539",
@"http://static2.dmcdn.net/static/video/624/848/51848426:jpeg_preview_small.jpg?20121105222523",
@"http://static2.dmcdn.net/static/video/281/448/51844182:jpeg_preview_small.jpg?20121105222502",
@"http://static2.dmcdn.net/static/video/414/848/51848414:jpeg_preview_small.jpg?20121105222516",
@"http://static2.dmcdn.net/static/video/171/848/51848171:jpeg_preview_small.jpg?20121105223449",
@"http://static2.dmcdn.net/static/video/904/848/51848409:jpeg_preview_small.jpg?20121105222514",
@"http://static2.dmcdn.net/static/video/004/848/51848400:jpeg_preview_small.jpg?20121105222443",
@"http://static2.dmcdn.net/static/video/693/848/51848396:jpeg_preview_small.jpg?20121105222439",
@"http://static2.dmcdn.net/static/video/401/848/51848104:jpeg_preview_small.jpg?20121105222832",
@"http://static2.dmcdn.net/static/video/957/648/51846759:jpeg_preview_small.jpg?20121105223109",
@"http://static2.dmcdn.net/static/video/603/848/51848306:jpeg_preview_small.jpg?20121105222324",
@"http://static2.dmcdn.net/static/video/990/848/51848099:jpeg_preview_small.jpg?20121105222807",
@"http://static2.dmcdn.net/static/video/929/448/51844929:jpeg_preview_small.jpg?20121105222216",
@"http://static2.dmcdn.net/static/video/320/548/51845023:jpeg_preview_small.jpg?20121105222214",
@"http://static2.dmcdn.net/static/video/387/448/51844783:jpeg_preview_small.jpg?20121105222212",
@"http://static2.dmcdn.net/static/video/833/248/51842338:jpeg_preview_small.jpg?20121105222209",
@"http://static2.dmcdn.net/static/video/993/348/51843399:jpeg_preview_small.jpg?20121105222012",
@"http://static2.dmcdn.net/static/video/660/848/51848066:jpeg_preview_small.jpg?20121105222754",
@"http://static2.dmcdn.net/static/video/471/848/51848174:jpeg_preview_small.jpg?20121105223419",
@"http://static2.dmcdn.net/static/video/255/748/51847552:jpeg_preview_small.jpg?20121105222420",
@"http://static2.dmcdn.net/static/video/257/448/51844752:jpeg_preview_small.jpg?20121105221728",
@"http://static2.dmcdn.net/static/video/090/848/51848090:jpeg_preview_small.jpg?20121105223020",
@"http://static2.dmcdn.net/static/video/807/448/51844708:jpeg_preview_small.jpg?20121105221654",
@"http://static2.dmcdn.net/static/video/196/448/51844691:jpeg_preview_small.jpg?20121105222110",
@"http://static2.dmcdn.net/static/video/406/448/51844604:jpeg_preview_small.jpg?20121105221647",
@"http://static2.dmcdn.net/static/video/865/348/51843568:jpeg_preview_small.jpg?20121105221644",
@"http://static2.dmcdn.net/static/video/932/448/51844239:jpeg_preview_small.jpg?20121105221309",
@"http://static2.dmcdn.net/static/video/967/438/51834769:jpeg_preview_small.jpg?20121105221020",
@"http://static2.dmcdn.net/static/video/362/348/51843263:jpeg_preview_small.jpg?20121105220855",
@"http://static2.dmcdn.net/static/video/777/448/51844777:jpeg_preview_small.jpg?20121105220715",
@"http://static2.dmcdn.net/static/video/567/348/51843765:jpeg_preview_small.jpg?20121105220708",
@"http://static2.dmcdn.net/static/video/905/248/51842509:jpeg_preview_small.jpg?20121105220640",
@"http://static2.dmcdn.net/static/video/857/748/51847758:jpeg_preview_small.jpg?20121105221003",
@"http://static2.dmcdn.net/static/video/578/348/51843875:jpeg_preview_small.jpg?20121105220350",
@"http://static2.dmcdn.net/static/video/214/448/51844412:jpeg_preview_small.jpg?20121105220415",
@"http://static2.dmcdn.net/static/video/264/748/51847462:jpeg_preview_small.jpg?20121105220635",
@"http://static2.dmcdn.net/static/video/817/748/51847718:jpeg_preview_small.jpg?20121105220233",
@"http://static2.dmcdn.net/static/video/784/848/51848487:jpeg_preview_small.jpg?20121105222704",
@"http://static2.dmcdn.net/static/video/182/448/51844281:jpeg_preview_small.jpg?20121105222652",
@"http://static2.dmcdn.net/static/video/801/848/51848108:jpeg_preview_small.jpg?20121105222907",
@"http://static2.dmcdn.net/static/video/974/848/51848479:jpeg_preview_small.jpg?20121105222657",
@"http://static2.dmcdn.net/static/video/274/848/51848472:jpeg_preview_small.jpg?20121105222644",
@"http://static2.dmcdn.net/static/video/954/848/51848459:jpeg_preview_small.jpg?20121105222637",
@"http://static2.dmcdn.net/static/video/554/848/51848455:jpeg_preview_small.jpg?20121105222615",
@"http://static2.dmcdn.net/static/video/944/848/51848449:jpeg_preview_small.jpg?20121105222558",
@"http://static2.dmcdn.net/static/video/144/848/51848441:jpeg_preview_small.jpg?20121105222556",
@"http://static2.dmcdn.net/static/video/134/848/51848431:jpeg_preview_small.jpg?20121105222539",
@"http://static2.dmcdn.net/static/video/624/848/51848426:jpeg_preview_small.jpg?20121105222523",
@"http://static2.dmcdn.net/static/video/281/448/51844182:jpeg_preview_small.jpg?20121105222502",
@"http://static2.dmcdn.net/static/video/414/848/51848414:jpeg_preview_small.jpg?20121105222516",
@"http://static2.dmcdn.net/static/video/171/848/51848171:jpeg_preview_small.jpg?20121105223449",
@"http://static2.dmcdn.net/static/video/904/848/51848409:jpeg_preview_small.jpg?20121105222514",
@"http://static2.dmcdn.net/static/video/004/848/51848400:jpeg_preview_small.jpg?20121105222443",
@"http://static2.dmcdn.net/static/video/693/848/51848396:jpeg_preview_small.jpg?20121105222439",
@"http://static2.dmcdn.net/static/video/401/848/51848104:jpeg_preview_small.jpg?20121105222832",
@"http://static2.dmcdn.net/static/video/957/648/51846759:jpeg_preview_small.jpg?20121105223109",
@"http://static2.dmcdn.net/static/video/603/848/51848306:jpeg_preview_small.jpg?20121105222324",
@"http://static2.dmcdn.net/static/video/990/848/51848099:jpeg_preview_small.jpg?20121105222807",
@"http://static2.dmcdn.net/static/video/929/448/51844929:jpeg_preview_small.jpg?20121105222216",
@"http://static2.dmcdn.net/static/video/320/548/51845023:jpeg_preview_small.jpg?20121105222214",
@"http://static2.dmcdn.net/static/video/387/448/51844783:jpeg_preview_small.jpg?20121105222212",
@"http://static2.dmcdn.net/static/video/833/248/51842338:jpeg_preview_small.jpg?20121105222209",
@"http://static2.dmcdn.net/static/video/993/348/51843399:jpeg_preview_small.jpg?20121105222012",
@"http://static2.dmcdn.net/static/video/660/848/51848066:jpeg_preview_small.jpg?20121105222754",
@"http://static2.dmcdn.net/static/video/471/848/51848174:jpeg_preview_small.jpg?20121105223419",
@"http://static2.dmcdn.net/static/video/255/748/51847552:jpeg_preview_small.jpg?20121105222420",
@"http://static2.dmcdn.net/static/video/257/448/51844752:jpeg_preview_small.jpg?20121105221728",
@"http://static2.dmcdn.net/static/video/090/848/51848090:jpeg_preview_small.jpg?20121105224514",
@"http://static2.dmcdn.net/static/video/807/448/51844708:jpeg_preview_small.jpg?20121105221654",
@"http://static2.dmcdn.net/static/video/196/448/51844691:jpeg_preview_small.jpg?20121105222110",
@"http://static2.dmcdn.net/static/video/406/448/51844604:jpeg_preview_small.jpg?20121105221647",
@"http://static2.dmcdn.net/static/video/865/348/51843568:jpeg_preview_small.jpg?20121105221644",
@"http://static2.dmcdn.net/static/video/932/448/51844239:jpeg_preview_small.jpg?20121105221309",
@"http://static2.dmcdn.net/static/video/967/438/51834769:jpeg_preview_small.jpg?20121105221020",
@"http://static2.dmcdn.net/static/video/362/348/51843263:jpeg_preview_small.jpg?20121105220855",
@"http://static2.dmcdn.net/static/video/777/448/51844777:jpeg_preview_small.jpg?20121105220715",
@"http://static2.dmcdn.net/static/video/567/348/51843765:jpeg_preview_small.jpg?20121105220708",
@"http://static2.dmcdn.net/static/video/905/248/51842509:jpeg_preview_small.jpg?20121105220640",
@"http://static2.dmcdn.net/static/video/857/748/51847758:jpeg_preview_small.jpg?20121105221003",
@"http://static2.dmcdn.net/static/video/578/348/51843875:jpeg_preview_small.jpg?20121105220350",
@"http://static2.dmcdn.net/static/video/214/448/51844412:jpeg_preview_small.jpg?20121105220415",
@"http://static2.dmcdn.net/static/video/264/748/51847462:jpeg_preview_small.jpg?20121105220635",
@"http://static2.dmcdn.net/static/video/817/748/51847718:jpeg_preview_small.jpg?20121105220233",
@"http://static2.dmcdn.net/static/video/807/748/51847708:jpeg_preview_small.jpg?20121105220241",
@"http://static2.dmcdn.net/static/video/199/838/51838991:jpeg_preview_small.jpg?20121105220605",
@"http://static2.dmcdn.net/static/video/776/748/51847677:jpeg_preview_small.jpg?20121105220150",
@"http://static2.dmcdn.net/static/video/986/748/51847689:jpeg_preview_small.jpg?20121105224514",
@"http://static2.dmcdn.net/static/video/915/748/51847519:jpeg_preview_small.jpg?20121105222216",
@"http://static2.dmcdn.net/static/video/983/448/51844389:jpeg_preview_small.jpg?20121105220116",
@"http://static2.dmcdn.net/static/video/751/348/51843157:jpeg_preview_small.jpg?20121105220104",
@"http://static2.dmcdn.net/static/video/192/538/51835291:jpeg_preview_small.jpg?20121105220103",
@"http://static2.dmcdn.net/static/video/596/448/51844695:jpeg_preview_small.jpg?20121105220033",
@"http://static2.dmcdn.net/static/video/750/648/51846057:jpeg_preview_small.jpg?20121105221259",
@"http://static2.dmcdn.net/static/video/441/148/51841144:jpeg_preview_small.jpg?20121105215911",
@"http://static2.dmcdn.net/static/video/860/448/51844068:jpeg_preview_small.jpg?20121105215905",
@"http://static2.dmcdn.net/static/video/995/748/51847599:jpeg_preview_small.jpg?20121105215939",
@"http://static2.dmcdn.net/static/video/774/748/51847477:jpeg_preview_small.jpg?20121105223414",
@"http://static2.dmcdn.net/static/video/498/648/51846894:jpeg_preview_small.jpg?20121105221807",
@"http://static2.dmcdn.net/static/video/011/748/51847110:jpeg_preview_small.jpg?20121105221118",
@"http://static2.dmcdn.net/static/video/794/748/51847497:jpeg_preview_small.jpg?20121105220829",
@"http://static2.dmcdn.net/static/video/988/648/51846889:jpeg_preview_small.jpg?20121105222149",
@"http://static2.dmcdn.net/static/video/769/548/51845967:jpeg_preview_small.jpg?20121105215601",
@"http://static2.dmcdn.net/static/video/225/448/51844522:jpeg_preview_small.jpg?20121105215552",
@"http://static2.dmcdn.net/static/video/172/308/51803271:jpeg_preview_small.jpg?20121105215455",
@"http://static2.dmcdn.net/static/video/994/748/51847499:jpeg_preview_small.jpg?20121105220343",
@"http://static2.dmcdn.net/static/video/852/748/51847258:jpeg_preview_small.jpg?20121105221031",
@"http://static2.dmcdn.net/static/video/671/838/51838176:jpeg_preview_small.jpg?20121105215421",
@"http://static2.dmcdn.net/static/video/172/448/51844271:jpeg_preview_small.jpg?20121105215420",
@"http://static2.dmcdn.net/static/video/735/448/51844537:jpeg_preview_small.jpg?20121105215437",
@"http://static2.dmcdn.net/static/video/834/448/51844438:jpeg_preview_small.jpg?20121105215431",
@"http://static2.dmcdn.net/static/video/613/448/51844316:jpeg_preview_small.jpg?20121105215431",
@"http://static2.dmcdn.net/static/video/581/748/51847185:jpeg_preview_small.jpg?20121105220637",
@"http://static2.dmcdn.net/static/video/407/648/51846704:jpeg_preview_small.jpg?20121105220316",
@"http://static2.dmcdn.net/static/video/460/448/51844064:jpeg_preview_small.jpg?20121105215245",
@"http://static2.dmcdn.net/static/video/298/648/51846892:jpeg_preview_small.jpg?20121105220953",
@"http://static2.dmcdn.net/static/video/053/748/51847350:jpeg_preview_small.jpg?20121105221113",
@"http://static2.dmcdn.net/static/video/996/448/51844699:jpeg_preview_small.jpg?20121105222807",
@"http://static2.dmcdn.net/static/video/451/448/51844154:jpeg_preview_small.jpg?20121105221955",
@"http://static2.dmcdn.net/static/video/049/648/51846940:jpeg_preview_small.jpg?20121105215910",
@"http://static2.dmcdn.net/static/video/091/748/51847190:jpeg_preview_small.jpg?20121105215617",
@"http://static2.dmcdn.net/static/video/573/748/51847375:jpeg_preview_small.jpg?20121105223420",
@"http://static2.dmcdn.net/static/video/103/248/51842301:jpeg_preview_small.jpg?20121105215014",
@"http://static2.dmcdn.net/static/video/991/548/51845199:jpeg_preview_small.jpg?20121105215407",
@"http://static2.dmcdn.net/static/video/872/648/51846278:jpeg_preview_small.jpg?20121105220635",
@"http://static2.dmcdn.net/static/video/813/748/51847318:jpeg_preview_small.jpg?20121105214729",
@"http://static2.dmcdn.net/static/video/153/448/51844351:jpeg_preview_small.jpg?20121105214622",
@"http://static2.dmcdn.net/static/video/328/648/51846823:jpeg_preview_small.jpg?20121105214944",
@"http://static2.dmcdn.net/static/video/892/748/51847298:jpeg_preview_small.jpg?20121105224514",
@"http://static2.dmcdn.net/static/video/640/048/51840046:jpeg_preview_small.jpg?20121105214430",
@"http://static2.dmcdn.net/static/video/153/648/51846351:jpeg_preview_small.jpg?20121105214426",
@"http://static2.dmcdn.net/static/video/769/248/51842967:jpeg_preview_small.jpg?20121105214255",
@"http://static2.dmcdn.net/static/video/720/448/51844027:jpeg_preview_small.jpg?20121105214248",
@"http://static2.dmcdn.net/static/video/895/048/51840598:jpeg_preview_small.jpg?20121105214234",
@"http://static2.dmcdn.net/static/video/893/348/51843398:jpeg_preview_small.jpg?20121105214157",
@"http://static2.dmcdn.net/static/video/351/748/51847153:jpeg_preview_small.jpg?20121105214106",
@"http://static2.dmcdn.net/static/video/364/648/51846463:jpeg_preview_small.jpg?20121105215005",
@"http://static2.dmcdn.net/static/video/269/938/51839962:jpeg_preview_small.jpg?20121105214014",
nil]; nil];
for (int i=0; i<100; i++) {
[_objects addObject:[NSString stringWithFormat:@"https://s3.amazonaws.com/fast-image-cache/demo-images/FICDDemoImage%03d.jpg", i]];
}
} }
[SDWebImageManager.sharedManager.imageDownloader setValue:@"SDWebImage Demo" forHTTPHeaderField:@"AppName"]; [SDWebImageManager.sharedManager.imageDownloader setValue:@"SDWebImage Demo" forHTTPHeaderField:@"AppName"];
SDWebImageManager.sharedManager.imageDownloader.executionOrder = SDWebImageDownloaderLIFOExecutionOrder; SDWebImageManager.sharedManager.imageDownloader.executionOrder = SDWebImageDownloaderLIFOExecutionOrder;
@ -85,9 +380,6 @@
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
} }
[cell.imageView setShowActivityIndicatorView:YES];
[cell.imageView setIndicatorStyle:UIActivityIndicatorViewStyleGray];
cell.textLabel.text = [NSString stringWithFormat:@"Image #%ld", (long)indexPath.row]; cell.textLabel.text = [NSString stringWithFormat:@"Image #%ld", (long)indexPath.row];
cell.imageView.contentMode = UIViewContentModeScaleAspectFill; cell.imageView.contentMode = UIViewContentModeScaleAspectFill;
[cell.imageView sd_setImageWithURL:[NSURL URLWithString:[_objects objectAtIndex:indexPath.row]] [cell.imageView sd_setImageWithURL:[NSURL URLWithString:[_objects objectAtIndex:indexPath.row]]

View File

@ -9,7 +9,7 @@
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string> <string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <string>com.dailymotion.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key> <key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string> <string>6.0</string>
<key>CFBundleName</key> <key>CFBundleName</key>
@ -24,11 +24,6 @@
<string>1.0</string> <string>1.0</string>
<key>LSRequiresIPhoneOS</key> <key>LSRequiresIPhoneOS</key>
<true/> <true/>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>UIRequiredDeviceCapabilities</key> <key>UIRequiredDeviceCapabilities</key>
<array> <array>
<string>armv7</string> <string>armv7</string>

View File

@ -1,4 +1,4 @@
Copyright (c) 2016 Olivier Poitrey rs@dailymotion.com Copyright (c) 2009 Olivier Poitrey <rs@dailymotion.com>
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

105
README.md
View File

@ -12,7 +12,7 @@ This library provides a category for UIImageView with support for remote images
It provides: It provides:
- An `UIImageView` category adding web image and cache management to the Cocoa Touch framework - An UIImageView category adding web image and cache management to the Cocoa Touch framework
- An asynchronous image downloader - An asynchronous image downloader
- An asynchronous memory + disk image caching with automatic cache expiration handling - An asynchronous memory + disk image caching with automatic cache expiration handling
- Animated GIF support - Animated GIF support
@ -25,12 +25,12 @@ It provides:
- Use GCD and ARC - Use GCD and ARC
- Arm64 support - Arm64 support
NOTE: Version 3.8 of SDWebImage requires iOS 7 or later (because of NSURLSession). NOTE: The version 3.0 of SDWebImage isn't fully backward compatible with 2.0 and requires iOS 5.1.1
Versions 3.7 to 3.0 requires iOS 5.1.1. If you need iOS < 5.0 support, please use the last [2.0 version](https://github.com/rs/SDWebImage/tree/2.0-compat). minimum deployement version. If you need iOS < 5.0 support, please use the last [2.0 version](https://github.com/rs/SDWebImage/tree/2.0-compat).
[How is SDWebImage better than X?](https://github.com/rs/SDWebImage/wiki/How-is-SDWebImage-better-than-X%3F) [How is SDWebImage better than X?](https://github.com/rs/SDWebImage/wiki/How-is-SDWebImage-better-than-X%3F)
Who Uses It Who Use 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/rs/SDWebImage/wiki/Who-Uses-SDWebImage) and add your app to the list.
@ -51,11 +51,14 @@ handled for you, from async downloads to caching management.
... ...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *MyIdentifier = @"MyIdentifier"; static NSString *MyIdentifier = @"MyIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier]; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:MyIdentifier] autorelease]; reuseIdentifier:MyIdentifier] autorelease];
} }
@ -71,16 +74,14 @@ handled for you, from async downloads to caching management.
### Using blocks ### Using blocks
With blocks, you can be notified about the image download progress and whenever the image retrieval With blocks, you can be notified about the image download progress and whenever the image retrival
has completed with success or not: has completed with success or not:
```objective-c ```objective-c
// Here we use the new provided sd_setImageWithURL: method to load the web image // Here we use the new provided sd_setImageWithURL: method to load the web image
[cell.imageView sd_setImageWithURL:[NSURL URLWithString:@"http://www.domain.com/path/to/image.jpg"] [cell.imageView sd_setImageWithURL:[NSURL URLWithString:@"http://www.domain.com/path/to/image.jpg"]
placeholderImage:[UIImage imageNamed:@"placeholder.png"] placeholderImage:[UIImage imageNamed:@"placeholder.png"]
completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) { completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {... completion code here ...}];
... completion code here ...
}];
``` ```
Note: neither your success nor failure block will be call if your image request is canceled before completion. Note: neither your success nor failure block will be call if your image request is canceled before completion.
@ -95,16 +96,16 @@ Here is a simple example of how to use SDWebImageManager:
```objective-c ```objective-c
SDWebImageManager *manager = [SDWebImageManager sharedManager]; SDWebImageManager *manager = [SDWebImageManager sharedManager];
[manager downloadImageWithURL:imageURL [manager loadImageWithURL:imageURL
options:0 options:0
progress:^(NSInteger receivedSize, NSInteger expectedSize) { progress:^(NSInteger receivedSize, NSInteger expectedSize) {
// progression tracking code // progression tracking code
} }
completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
if (image) { if (image) {
// do something with image // do something with image
} }
}]; }];
``` ```
### Using Asynchronous Image Downloader Independently ### Using Asynchronous Image Downloader Independently
@ -112,17 +113,19 @@ SDWebImageManager *manager = [SDWebImageManager sharedManager];
It's also possible to use the async image downloader independently: It's also possible to use the async image downloader independently:
```objective-c ```objective-c
SDWebImageDownloader *downloader = [SDWebImageDownloader sharedDownloader]; [SDWebImageDownloader.sharedDownloader downloadImageWithURL:imageURL
[downloader downloadImageWithURL:imageURL options:0
options:0 progress:^(NSInteger receivedSize, NSInteger expectedSize)
progress:^(NSInteger receivedSize, NSInteger expectedSize) { {
// progression tracking code // progression tracking code
} }
completed:^(UIImage *image, NSData *data, NSError *error, BOOL finished) { completed:^(UIImage *image, NSData *data, NSError *error, BOOL finished)
if (image && finished) { {
// do something with image if (image && finished)
} {
}]; // do something with image
}
}];
``` ```
### Using Asynchronous Image Caching Independently ### Using Asynchronous Image Caching Independently
@ -141,7 +144,8 @@ the image.
```objective-c ```objective-c
SDImageCache *imageCache = [[SDImageCache alloc] initWithNamespace:@"myNamespace"]; SDImageCache *imageCache = [[SDImageCache alloc] initWithNamespace:@"myNamespace"];
[imageCache queryDiskCacheForKey:myCacheKey done:^(UIImage *image) { [imageCache queryDiskCacheForKey:myCacheKey done:^(UIImage *image)
{
// image is not nil if image was found // image is not nil if image was found
}]; }];
``` ```
@ -169,7 +173,8 @@ The following example sets a filter in the application delegate that will remove
the URL before to use it as a cache key: the URL before to use it as a cache key:
```objective-c ```objective-c
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
SDWebImageManager.sharedManager.cacheKeyFilter = ^(NSURL *url) { SDWebImageManager.sharedManager.cacheKeyFilter = ^(NSURL *url) {
url = [[NSURL alloc] initWithScheme:url.scheme host:url.host path:url.path]; url = [[NSURL alloc] initWithScheme:url.scheme host:url.host path:url.path];
return [url absoluteString]; return [url absoluteString];
@ -213,7 +218,7 @@ Installation
------------ ------------
There are three ways to use SDWebImage in your project: There are three ways to use SDWebImage in your project:
- using CocoaPods - using Cocoapods
- copying all the files into your project - copying all the files into your project
- importing the project as a static library - importing the project as a static library
@ -223,28 +228,13 @@ There are three ways to use SDWebImage in your project:
#### Podfile #### Podfile
``` ```
platform :ios, '7.0' platform :ios, '6.1'
pod 'SDWebImage', '~>3.8' pod 'SDWebImage', '~>3.7'
```
If you are using Swift, be sure to add `use_frameworks!` and set your target to iOS 8+:
```
platform :ios, '8.0'
use_frameworks!
```
#### Subspecs
There are 3 subspecs available now: `Core`, `MapKit` and `WebP` (this means you can install only some of the SDWebImage modules. By default, you get just `Core`, so if you need `WebP`, you need to specify it).
Podfile example:
```
pod 'SDWebImage/WebP'
``` ```
### Installation with Carthage (iOS 8+) ### Installation with Carthage (iOS 8+)
[Carthage](https://github.com/Carthage/Carthage) is a lightweight dependency manager for Swift and Objective-C. It leverages CocoaTouch modules and is less invasive than CocoaPods. [Carthage](https://github.com/Carthage/Carthage) is a lightweight dependency manager for Swift and Objective-C. It leverages CocoaTouch modules and ins less invasive than CocoaPods.
To install with carthage, follow the instruction on [Carthage](https://github.com/Carthage/Carthage) To install with carthage, follow the instruction on [Carthage](https://github.com/Carthage/Carthage)
@ -256,14 +246,9 @@ github "rs/SDWebImage"
#### Usage #### Usage
Swift Swift
If you installed using CocoaPods:
```
import SDWebImage
```
If you installed manually:
``` ```
import WebImage import WebImage
``` ```
Objective-C Objective-C
@ -306,10 +291,6 @@ If you're using Cocoa Pods and have any frameworks that extend optional librarie
``` ```
-force_load $(TARGET_BUILD_DIR)/libPods.a -force_load $(TARGET_BUILD_DIR)/libPods.a
``` ```
and this:
```
$(inherited)
```
### Import headers in your source files ### Import headers in your source files

View File

@ -1,8 +1,7 @@
Pod::Spec.new do |s| Pod::Spec.new do |s|
s.name = 'SDWebImage' s.name = 'SDWebImage'
s.version = '3.8.1' s.version = '3.7.3'
s.ios.deployment_target = '7.0' s.platform = :ios, '5.0'
s.tvos.deployment_target = '9.0'
s.license = 'MIT' s.license = 'MIT'
s.summary = 'Asynchronous image downloader with cache support with an UIImageView category.' s.summary = 'Asynchronous image downloader with cache support with an UIImageView category.'
s.homepage = 'https://github.com/rs/SDWebImage' s.homepage = 'https://github.com/rs/SDWebImage'
@ -25,11 +24,9 @@ Pod::Spec.new do |s|
s.subspec 'Core' do |core| s.subspec 'Core' do |core|
core.source_files = 'SDWebImage/{NS,SD,UI}*.{h,m}' core.source_files = 'SDWebImage/{NS,SD,UI}*.{h,m}'
core.exclude_files = 'SDWebImage/UIImage+WebP.{h,m}' core.exclude_files = 'SDWebImage/UIImage+WebP.{h,m}'
core.tvos.exclude_files = 'SDWebImage/MKAnnotationView+WebCache.*'
end end
s.subspec 'MapKit' do |mk| s.subspec 'MapKit' do |mk|
mk.ios.deployment_target = '7.0'
mk.source_files = 'SDWebImage/MKAnnotationView+WebCache.*' mk.source_files = 'SDWebImage/MKAnnotationView+WebCache.*'
mk.framework = 'MapKit' mk.framework = 'MapKit'
mk.dependency 'SDWebImage/Core' mk.dependency 'SDWebImage/Core'
@ -37,10 +34,7 @@ Pod::Spec.new do |s|
s.subspec 'WebP' do |webp| s.subspec 'WebP' do |webp|
webp.source_files = 'SDWebImage/UIImage+WebP.{h,m}' webp.source_files = 'SDWebImage/UIImage+WebP.{h,m}'
webp.xcconfig = { webp.xcconfig = { 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) SD_WEBP=1' }
'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) SD_WEBP=1',
'USER_HEADER_SEARCH_PATHS' => '$(inherited) $(SRCROOT)/libwebp/src'
}
webp.dependency 'SDWebImage/Core' webp.dependency 'SDWebImage/Core'
webp.dependency 'libwebp' webp.dependency 'libwebp'
end end

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "0710" LastUpgradeVersion = "0630"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"
@ -23,24 +23,21 @@
</BuildActionEntries> </BuildActionEntries>
</BuildAction> </BuildAction>
<TestAction <TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"> shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
<Testables> <Testables>
</Testables> </Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction> </TestAction>
<LaunchAction <LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0" launchStyle = "0"
useCustomWorkingDirectory = "NO" useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO" ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES" debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES"> allowLocationSimulation = "YES">
<MacroExpansion> <MacroExpansion>
<BuildableReference <BuildableReference
@ -55,10 +52,10 @@
</AdditionalOptions> </AdditionalOptions>
</LaunchAction> </LaunchAction>
<ProfileAction <ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES" shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = "" savedToolIdentifier = ""
useCustomWorkingDirectory = "NO" useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES"> debugDocumentVersioning = "YES">
<MacroExpansion> <MacroExpansion>
<BuildableReference <BuildableReference

View File

@ -16,9 +16,6 @@
<FileRef <FileRef
location = "group:SDWebImage.podspec"> location = "group:SDWebImage.podspec">
</FileRef> </FileRef>
<FileRef
location = "group:CHANGELOG.md">
</FileRef>
<FileRef <FileRef
location = "group:Tests/Pods/Pods.xcodeproj"> location = "group:Tests/Pods/Pods.xcodeproj">
</FileRef> </FileRef>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "0710" LastUpgradeVersion = "0510"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"
@ -23,10 +23,10 @@
</BuildActionEntries> </BuildActionEntries>
</BuildAction> </BuildAction>
<TestAction <TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"> shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
<Testables> <Testables>
</Testables> </Testables>
<MacroExpansion> <MacroExpansion>
@ -38,21 +38,17 @@
ReferencedContainer = "container:Examples/SDWebImage Demo.xcodeproj"> ReferencedContainer = "container:Examples/SDWebImage Demo.xcodeproj">
</BuildableReference> </BuildableReference>
</MacroExpansion> </MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction> </TestAction>
<LaunchAction <LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0" launchStyle = "0"
useCustomWorkingDirectory = "NO" useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO" ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES" debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES"> allowLocationSimulation = "YES">
<BuildableProductRunnable <BuildableProductRunnable>
runnableDebuggingMode = "0">
<BuildableReference <BuildableReference
BuildableIdentifier = "primary" BuildableIdentifier = "primary"
BlueprintIdentifier = "53761294155AB74D005750A4" BlueprintIdentifier = "53761294155AB74D005750A4"
@ -65,13 +61,12 @@
</AdditionalOptions> </AdditionalOptions>
</LaunchAction> </LaunchAction>
<ProfileAction <ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES" shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = "" savedToolIdentifier = ""
useCustomWorkingDirectory = "NO" useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES"> debugDocumentVersioning = "YES">
<BuildableProductRunnable <BuildableProductRunnable>
runnableDebuggingMode = "0">
<BuildableReference <BuildableReference
BuildableIdentifier = "primary" BuildableIdentifier = "primary"
BlueprintIdentifier = "53761294155AB74D005750A4" BlueprintIdentifier = "53761294155AB74D005750A4"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "0710" LastUpgradeVersion = "0640"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"
@ -14,40 +14,37 @@
buildForAnalyzing = "YES"> buildForAnalyzing = "YES">
<BuildableReference <BuildableReference
BuildableIdentifier = "primary" BuildableIdentifier = "primary"
BlueprintIdentifier = "00733A4B1BC487C000A5A117" BlueprintIdentifier = "DA4D3BEF1B552F4100EC8389"
BuildableName = "WebImage.framework" BuildableName = "libSDWebImage+All.a"
BlueprintName = "WebImage tvOS" BlueprintName = "SDWebImage+All"
ReferencedContainer = "container:SDWebImage.xcodeproj"> ReferencedContainer = "container:SDWebImage.xcodeproj">
</BuildableReference> </BuildableReference>
</BuildActionEntry> </BuildActionEntry>
</BuildActionEntries> </BuildActionEntries>
</BuildAction> </BuildAction>
<TestAction <TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"> shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
<Testables> <Testables>
</Testables> </Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction> </TestAction>
<LaunchAction <LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0" launchStyle = "0"
useCustomWorkingDirectory = "NO" useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO" ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES" debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES"> allowLocationSimulation = "YES">
<MacroExpansion> <MacroExpansion>
<BuildableReference <BuildableReference
BuildableIdentifier = "primary" BuildableIdentifier = "primary"
BlueprintIdentifier = "00733A4B1BC487C000A5A117" BlueprintIdentifier = "DA4D3BEF1B552F4100EC8389"
BuildableName = "WebImage.framework" BuildableName = "libSDWebImage+All.a"
BlueprintName = "WebImage tvOS" BlueprintName = "SDWebImage+All"
ReferencedContainer = "container:SDWebImage.xcodeproj"> ReferencedContainer = "container:SDWebImage.xcodeproj">
</BuildableReference> </BuildableReference>
</MacroExpansion> </MacroExpansion>
@ -55,17 +52,17 @@
</AdditionalOptions> </AdditionalOptions>
</LaunchAction> </LaunchAction>
<ProfileAction <ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES" shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = "" savedToolIdentifier = ""
useCustomWorkingDirectory = "NO" useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES"> debugDocumentVersioning = "YES">
<MacroExpansion> <MacroExpansion>
<BuildableReference <BuildableReference
BuildableIdentifier = "primary" BuildableIdentifier = "primary"
BlueprintIdentifier = "00733A4B1BC487C000A5A117" BlueprintIdentifier = "DA4D3BEF1B552F4100EC8389"
BuildableName = "WebImage.framework" BuildableName = "libSDWebImage+All.a"
BlueprintName = "WebImage tvOS" BlueprintName = "SDWebImage+All"
ReferencedContainer = "container:SDWebImage.xcodeproj"> ReferencedContainer = "container:SDWebImage.xcodeproj">
</BuildableReference> </BuildableReference>
</MacroExpansion> </MacroExpansion>

View File

@ -0,0 +1,77 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0640"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "4389D6EE1B545EE0009F647B"
BuildableName = "libSDWebImage+GIF.a"
BlueprintName = "SDWebImage+GIF"
ReferencedContainer = "container:SDWebImage.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
<Testables>
</Testables>
</TestAction>
<LaunchAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "4389D6EE1B545EE0009F647B"
BuildableName = "libSDWebImage+GIF.a"
BlueprintName = "SDWebImage+GIF"
ReferencedContainer = "container:SDWebImage.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "4389D6EE1B545EE0009F647B"
BuildableName = "libSDWebImage+GIF.a"
BlueprintName = "SDWebImage+GIF"
ReferencedContainer = "container:SDWebImage.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "0710" LastUpgradeVersion = "0510"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"
@ -23,24 +23,21 @@
</BuildActionEntries> </BuildActionEntries>
</BuildAction> </BuildAction>
<TestAction <TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"> shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
<Testables> <Testables>
</Testables> </Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction> </TestAction>
<LaunchAction <LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0" launchStyle = "0"
useCustomWorkingDirectory = "NO" useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO" ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES" debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES"> allowLocationSimulation = "YES">
<MacroExpansion> <MacroExpansion>
<BuildableReference <BuildableReference
@ -55,10 +52,10 @@
</AdditionalOptions> </AdditionalOptions>
</LaunchAction> </LaunchAction>
<ProfileAction <ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES" shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = "" savedToolIdentifier = ""
useCustomWorkingDirectory = "NO" useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES"> debugDocumentVersioning = "YES">
</ProfileAction> </ProfileAction>
<AnalyzeAction <AnalyzeAction

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "0710" LastUpgradeVersion = "0510"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"
@ -23,24 +23,21 @@
</BuildActionEntries> </BuildActionEntries>
</BuildAction> </BuildAction>
<TestAction <TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"> shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
<Testables> <Testables>
</Testables> </Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction> </TestAction>
<LaunchAction <LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0" launchStyle = "0"
useCustomWorkingDirectory = "NO" useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO" ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES" debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES"> allowLocationSimulation = "YES">
<MacroExpansion> <MacroExpansion>
<BuildableReference <BuildableReference
@ -55,10 +52,10 @@
</AdditionalOptions> </AdditionalOptions>
</LaunchAction> </LaunchAction>
<ProfileAction <ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES" shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = "" savedToolIdentifier = ""
useCustomWorkingDirectory = "NO" useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES"> debugDocumentVersioning = "YES">
</ProfileAction> </ProfileAction>
<AnalyzeAction <AnalyzeAction

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "0710" LastUpgradeVersion = "0510"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"
@ -23,24 +23,21 @@
</BuildActionEntries> </BuildActionEntries>
</BuildAction> </BuildAction>
<TestAction <TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"> shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
<Testables> <Testables>
</Testables> </Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction> </TestAction>
<LaunchAction <LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0" launchStyle = "0"
useCustomWorkingDirectory = "NO" useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO" ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES" debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES"> allowLocationSimulation = "YES">
<MacroExpansion> <MacroExpansion>
<BuildableReference <BuildableReference
@ -55,10 +52,10 @@
</AdditionalOptions> </AdditionalOptions>
</LaunchAction> </LaunchAction>
<ProfileAction <ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES" shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = "" savedToolIdentifier = ""
useCustomWorkingDirectory = "NO" useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES"> debugDocumentVersioning = "YES">
</ProfileAction> </ProfileAction>
<AnalyzeAction <AnalyzeAction

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "0710" LastUpgradeVersion = "0510"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"
@ -23,24 +23,21 @@
</BuildActionEntries> </BuildActionEntries>
</BuildAction> </BuildAction>
<TestAction <TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"> shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
<Testables> <Testables>
</Testables> </Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction> </TestAction>
<LaunchAction <LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0" launchStyle = "0"
useCustomWorkingDirectory = "NO" useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO" ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES" debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES"> allowLocationSimulation = "YES">
<MacroExpansion> <MacroExpansion>
<BuildableReference <BuildableReference
@ -55,10 +52,10 @@
</AdditionalOptions> </AdditionalOptions>
</LaunchAction> </LaunchAction>
<ProfileAction <ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES" shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = "" savedToolIdentifier = ""
useCustomWorkingDirectory = "NO" useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES"> debugDocumentVersioning = "YES">
</ProfileAction> </ProfileAction>
<AnalyzeAction <AnalyzeAction

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "0710" LastUpgradeVersion = "0610"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"
@ -23,10 +23,10 @@
</BuildActionEntries> </BuildActionEntries>
</BuildAction> </BuildAction>
<TestAction <TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"> shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
<Testables> <Testables>
<TestableReference <TestableReference
skipped = "NO"> skipped = "NO">
@ -48,18 +48,15 @@
ReferencedContainer = "container:Tests/SDWebImage Tests.xcodeproj"> ReferencedContainer = "container:Tests/SDWebImage Tests.xcodeproj">
</BuildableReference> </BuildableReference>
</MacroExpansion> </MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction> </TestAction>
<LaunchAction <LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0" launchStyle = "0"
useCustomWorkingDirectory = "NO" useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO" ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES" debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES"> allowLocationSimulation = "YES">
<MacroExpansion> <MacroExpansion>
<BuildableReference <BuildableReference
@ -74,10 +71,10 @@
</AdditionalOptions> </AdditionalOptions>
</LaunchAction> </LaunchAction>
<ProfileAction <ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES" shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = "" savedToolIdentifier = ""
useCustomWorkingDirectory = "NO" useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES"> debugDocumentVersioning = "YES">
<MacroExpansion> <MacroExpansion>
<BuildableReference <BuildableReference

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "0710" LastUpgradeVersion = "0630"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"
@ -23,24 +23,21 @@
</BuildActionEntries> </BuildActionEntries>
</BuildAction> </BuildAction>
<TestAction <TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"> shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
<Testables> <Testables>
</Testables> </Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction> </TestAction>
<LaunchAction <LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0" launchStyle = "0"
useCustomWorkingDirectory = "NO" useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO" ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES" debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES"> allowLocationSimulation = "YES">
<MacroExpansion> <MacroExpansion>
<BuildableReference <BuildableReference
@ -55,10 +52,10 @@
</AdditionalOptions> </AdditionalOptions>
</LaunchAction> </LaunchAction>
<ProfileAction <ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES" shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = "" savedToolIdentifier = ""
useCustomWorkingDirectory = "NO" useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES"> debugDocumentVersioning = "YES">
<MacroExpansion> <MacroExpansion>
<BuildableReference <BuildableReference

View File

@ -63,7 +63,7 @@
* @param completedBlock A block called when operation has been completed. This block has no return value * @param completedBlock A block called when operation has been completed. This block has no return value
* and takes the requested UIImage as first parameter. In case of error the image parameter * and takes the requested UIImage as first parameter. In case of error the image parameter
* is nil and the second parameter may contain an NSError. The third parameter is a Boolean * is nil and the second parameter may contain an NSError. The third parameter is a Boolean
* indicating if the image was retrieved from the local cache or from the network. * indicating if the image was retrived from the local cache or from the network.
* The fourth parameter is the original image url. * The fourth parameter is the original image url.
*/ */
- (void)sd_setImageWithURL:(NSURL *)url completed:(SDWebImageCompletionBlock)completedBlock; - (void)sd_setImageWithURL:(NSURL *)url completed:(SDWebImageCompletionBlock)completedBlock;
@ -78,7 +78,7 @@
* @param completedBlock A block called when operation has been completed. This block has no return value * @param completedBlock A block called when operation has been completed. This block has no return value
* and takes the requested UIImage as first parameter. In case of error the image parameter * and takes the requested UIImage as first parameter. In case of error the image parameter
* is nil and the second parameter may contain an NSError. The third parameter is a Boolean * is nil and the second parameter may contain an NSError. The third parameter is a Boolean
* indicating if the image was retrieved from the local cache or from the network. * indicating if the image was retrived from the local cache or from the network.
* The fourth parameter is the original image url. * The fourth parameter is the original image url.
*/ */
- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletionBlock)completedBlock; - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletionBlock)completedBlock;
@ -94,7 +94,7 @@
* @param completedBlock A block called when operation has been completed. This block has no return value * @param completedBlock A block called when operation has been completed. This block has no return value
* and takes the requested UIImage as first parameter. In case of error the image parameter * and takes the requested UIImage as first parameter. In case of error the image parameter
* is nil and the second parameter may contain an NSError. The third parameter is a Boolean * is nil and the second parameter may contain an NSError. The third parameter is a Boolean
* indicating if the image was retrieved from the local cache or from the network. * indicating if the image was retrived from the local cache or from the network.
* The fourth parameter is the original image url. * The fourth parameter is the original image url.
*/ */
- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock; - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock;
@ -105,20 +105,3 @@
- (void)sd_cancelCurrentImageLoad; - (void)sd_cancelCurrentImageLoad;
@end @end
@interface MKAnnotationView (WebCacheDeprecated)
- (NSURL *)imageURL __deprecated_msg("Use `sd_imageURL`");
- (void)setImageWithURL:(NSURL *)url __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:`");
- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:placeholderImage:`");
- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:placeholderImage:options:`");
- (void)setImageWithURL:(NSURL *)url completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:completed:`");
- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:placeholderImage:completed:`");
- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:placeholderImage:options:completed:`");
- (void)cancelCurrentImageLoad __deprecated_msg("Use `sd_cancelCurrentImageLoad`");
@end

View File

@ -46,22 +46,13 @@ static char imageURLKey;
if (url) { if (url) {
__weak __typeof(self)wself = self; __weak __typeof(self)wself = self;
id <SDWebImageOperation> operation = [SDWebImageManager.sharedManager downloadImageWithURL:url options:options progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { id <SDWebImageOperation> operation = [SDWebImageManager.sharedManager loadImageWithURL:url options:options progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
if (!wself) return; if (!wself) return;
dispatch_main_sync_safe(^{ dispatch_main_sync_safe(^{
__strong MKAnnotationView *sself = wself; __strong MKAnnotationView *sself = wself;
if (!sself) return; if (!sself) return;
if (image && (options & SDWebImageAvoidAutoSetImage) && completedBlock) { if (image) {
completedBlock(image, error, cacheType, url); sself.image = image;
return;
} else if (image) {
wself.image = image;
[wself setNeedsLayout];
} else {
if ((options & SDWebImageDelayPlaceholder)) {
wself.image = placeholder;
[wself setNeedsLayout];
}
} }
if (completedBlock && finished) { if (completedBlock && finished) {
completedBlock(image, error, cacheType, url); completedBlock(image, error, cacheType, url);
@ -84,52 +75,3 @@ static char imageURLKey;
} }
@end @end
@implementation MKAnnotationView (WebCacheDeprecated)
- (NSURL *)imageURL {
return [self sd_imageURL];
}
- (void)setImageWithURL:(NSURL *)url {
[self sd_setImageWithURL:url placeholderImage:nil options:0 completed:nil];
}
- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder {
[self sd_setImageWithURL:url placeholderImage:placeholder options:0 completed:nil];
}
- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options {
[self sd_setImageWithURL:url placeholderImage:placeholder options:options completed:nil];
}
- (void)setImageWithURL:(NSURL *)url completed:(SDWebImageCompletedBlock)completedBlock {
[self sd_setImageWithURL:url placeholderImage:nil options:0 completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
if (completedBlock) {
completedBlock(image, error, cacheType);
}
}];
}
- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletedBlock)completedBlock {
[self sd_setImageWithURL:url placeholderImage:placeholder options:0 completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
if (completedBlock) {
completedBlock(image, error, cacheType);
}
}];
}
- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletedBlock)completedBlock {
[self sd_setImageWithURL:url placeholderImage:placeholder options:options completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
if (completedBlock) {
completedBlock(image, error, cacheType);
}
}];
}
- (void)cancelCurrentImageLoad {
[self sd_cancelCurrentImageLoad];
}
@end

View File

@ -17,10 +17,3 @@
+ (NSString *)sd_contentTypeForImageData:(NSData *)data; + (NSString *)sd_contentTypeForImageData:(NSData *)data;
@end @end
@interface NSData (ImageContentTypeDeprecated)
+ (NSString *)contentTypeForImageData:(NSData *)data __deprecated_msg("Use `sd_contentTypeForImageData:`");
@end

View File

@ -38,12 +38,3 @@
} }
@end @end
@implementation NSData (ImageContentTypeDeprecated)
+ (NSString *)contentTypeForImageData:(NSData *)data {
return [self sd_contentTypeForImageData:data];
}
@end

View File

@ -37,21 +37,11 @@ typedef void(^SDWebImageCalculateSizeBlock)(NSUInteger fileCount, NSUInteger tot
@interface SDImageCache : NSObject @interface SDImageCache : NSObject
/** /**
* Decompressing images that are downloaded and cached can improve performance but can consume lot of memory. * Decompressing images that are downloaded and cached can improve peformance but can consume lot of memory.
* Defaults to YES. Set this to NO if you are experiencing a crash due to excessive memory consumption. * Defaults to YES. Set this to NO if you are experiencing a crash due to excessive memory consumption.
*/ */
@property (assign, nonatomic) BOOL shouldDecompressImages; @property (assign, nonatomic) BOOL shouldDecompressImages;
/**
* disable iCloud backup [defaults to YES]
*/
@property (assign, nonatomic) BOOL shouldDisableiCloud;
/**
* use memory cache [defaults to YES]
*/
@property (assign, nonatomic) BOOL shouldCacheImagesInMemory;
/** /**
* The maximum "total cost" of the in-memory image cache. The cost function is the number of pixels held in memory. * The maximum "total cost" of the in-memory image cache. The cost function is the number of pixels held in memory.
*/ */
@ -134,14 +124,6 @@ typedef void(^SDWebImageCalculateSizeBlock)(NSUInteger fileCount, NSUInteger tot
*/ */
- (void)storeImage:(UIImage *)image recalculateFromImage:(BOOL)recalculate imageData:(NSData *)imageData forKey:(NSString *)key toDisk:(BOOL)toDisk; - (void)storeImage:(UIImage *)image recalculateFromImage:(BOOL)recalculate imageData:(NSData *)imageData forKey:(NSString *)key toDisk:(BOOL)toDisk;
/**
* Store image NSData into disk cache at the given key.
*
* @param imageData The image data to store
* @param key The unique image cache key, usually it's image absolute URL
*/
- (void)storeImageDataToDisk:(NSData *)imageData forKey:(NSString *)key;
/** /**
* Query the disk cache asynchronously. * Query the disk cache asynchronously.
* *
@ -164,7 +146,7 @@ typedef void(^SDWebImageCalculateSizeBlock)(NSUInteger fileCount, NSUInteger tot
- (UIImage *)imageFromDiskCacheForKey:(NSString *)key; - (UIImage *)imageFromDiskCacheForKey:(NSString *)key;
/** /**
* Remove the image from memory and disk cache asynchronously * Remove the image from memory and disk cache synchronously
* *
* @param key The unique image cache key * @param key The unique image cache key
*/ */
@ -262,7 +244,7 @@ typedef void(^SDWebImageCalculateSizeBlock)(NSUInteger fileCount, NSUInteger tot
* Get the cache path for a certain key (needs the cache path root folder) * Get the cache path for a certain key (needs the cache path root folder)
* *
* @param key the key (can be obtained from url using cacheKeyForURL) * @param key the key (can be obtained from url using cacheKeyForURL)
* @param path the cache path root folder * @param path the cach path root folder
* *
* @return the cache path * @return the cache path
*/ */

View File

@ -116,17 +116,11 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
// Set decompression to YES // Set decompression to YES
_shouldDecompressImages = YES; _shouldDecompressImages = YES;
// memory cache enabled
_shouldCacheImagesInMemory = YES;
// Disable iCloud
_shouldDisableiCloud = YES;
dispatch_sync(_ioQueue, ^{ dispatch_sync(_ioQueue, ^{
_fileManager = [NSFileManager new]; _fileManager = [NSFileManager new];
}); });
#if TARGET_OS_IOS #if TARGET_OS_IPHONE
// Subscribe to app events // Subscribe to app events
[[NSNotificationCenter defaultCenter] addObserver:self [[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(clearMemory) selector:@selector(clearMemory)
@ -181,9 +175,8 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
} }
unsigned char r[CC_MD5_DIGEST_LENGTH]; unsigned char r[CC_MD5_DIGEST_LENGTH];
CC_MD5(str, (CC_LONG)strlen(str), r); CC_MD5(str, (CC_LONG)strlen(str), r);
NSString *filename = [NSString stringWithFormat:@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%@", 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[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]];
r[11], r[12], r[13], r[14], r[15], [[key pathExtension] isEqualToString:@""] ? @"" : [NSString stringWithFormat:@".%@", [key pathExtension]]];
return filename; return filename;
} }
@ -200,11 +193,9 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
if (!image || !key) { if (!image || !key) {
return; return;
} }
// if memory cache is enabled
if (self.shouldCacheImagesInMemory) { NSUInteger cost = SDCacheCostForImage(image);
NSUInteger cost = SDCacheCostForImage(image); [self.memCache setObject:image forKey:key cost:cost];
[self.memCache setObject:image forKey:key cost:cost];
}
if (toDisk) { if (toDisk) {
dispatch_async(self.ioQueue, ^{ dispatch_async(self.ioQueue, ^{
@ -241,7 +232,13 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
#endif #endif
} }
[self storeImageDataToDisk:data forKey:key]; if (data) {
if (![_fileManager fileExistsAtPath:_diskCachePath]) {
[_fileManager createDirectoryAtPath:_diskCachePath withIntermediateDirectories:YES attributes:nil error:NULL];
}
[_fileManager createFileAtPath:[self defaultCachePathForKey:key] contents:data attributes:nil];
}
}); });
} }
} }
@ -254,41 +251,12 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
[self storeImage:image recalculateFromImage:YES imageData:nil forKey:key toDisk:toDisk]; [self storeImage:image recalculateFromImage:YES imageData:nil forKey:key toDisk:toDisk];
} }
- (void)storeImageDataToDisk:(NSData *)imageData forKey:(NSString *)key {
if (!imageData) {
return;
}
if (![_fileManager fileExistsAtPath:_diskCachePath]) {
[_fileManager createDirectoryAtPath:_diskCachePath withIntermediateDirectories:YES attributes:nil error:NULL];
}
// get cache Path for image key
NSString *cachePathForKey = [self defaultCachePathForKey:key];
// transform to NSUrl
NSURL *fileURL = [NSURL fileURLWithPath:cachePathForKey];
[_fileManager createFileAtPath:cachePathForKey contents:imageData attributes:nil];
// disable iCloud backup
if (self.shouldDisableiCloud) {
[fileURL setResourceValue:[NSNumber numberWithBool:YES] forKey:NSURLIsExcludedFromBackupKey error:nil];
}
}
- (BOOL)diskImageExistsWithKey:(NSString *)key { - (BOOL)diskImageExistsWithKey:(NSString *)key {
BOOL exists = NO; BOOL exists = NO;
// this is an exception to access the filemanager on another queue than ioQueue, but we are using the shared instance // this is an exception to access the filemanager on another queue than ioQueue, but we are using the shared instance
// from apple docs on NSFileManager: The methods of the shared NSFileManager object can be called from multiple threads safely. // from apple docs on NSFileManager: The methods of the shared NSFileManager object can be called from multiple threads safely.
exists = [[NSFileManager defaultManager] fileExistsAtPath:[self defaultCachePathForKey:key]]; exists = [[NSFileManager defaultManager] fileExistsAtPath:[self defaultCachePathForKey:key]];
// fallback because of https://github.com/rs/SDWebImage/pull/976 that added the extension to the disk file name
// checking the key with and without the extension
if (!exists) {
exists = [[NSFileManager defaultManager] fileExistsAtPath:[[self defaultCachePathForKey:key] stringByDeletingPathExtension]];
}
return exists; return exists;
} }
@ -296,13 +264,6 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
- (void)diskImageExistsWithKey:(NSString *)key completion:(SDWebImageCheckCacheCompletionBlock)completionBlock { - (void)diskImageExistsWithKey:(NSString *)key completion:(SDWebImageCheckCacheCompletionBlock)completionBlock {
dispatch_async(_ioQueue, ^{ dispatch_async(_ioQueue, ^{
BOOL exists = [_fileManager fileExistsAtPath:[self defaultCachePathForKey:key]]; BOOL exists = [_fileManager fileExistsAtPath:[self defaultCachePathForKey:key]];
// fallback because of https://github.com/rs/SDWebImage/pull/976 that added the extension to the disk file name
// checking the key with and without the extension
if (!exists) {
exists = [_fileManager fileExistsAtPath:[[self defaultCachePathForKey:key] stringByDeletingPathExtension]];
}
if (completionBlock) { if (completionBlock) {
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
completionBlock(exists); completionBlock(exists);
@ -316,7 +277,6 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
} }
- (UIImage *)imageFromDiskCacheForKey:(NSString *)key { - (UIImage *)imageFromDiskCacheForKey:(NSString *)key {
// First check the in-memory cache... // First check the in-memory cache...
UIImage *image = [self imageFromMemoryCacheForKey:key]; UIImage *image = [self imageFromMemoryCacheForKey:key];
if (image) { if (image) {
@ -325,7 +285,7 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
// Second check the disk cache... // Second check the disk cache...
UIImage *diskImage = [self diskImageForKey:key]; UIImage *diskImage = [self diskImageForKey:key];
if (diskImage && self.shouldCacheImagesInMemory) { if (diskImage) {
NSUInteger cost = SDCacheCostForImage(diskImage); NSUInteger cost = SDCacheCostForImage(diskImage);
[self.memCache setObject:diskImage forKey:key cost:cost]; [self.memCache setObject:diskImage forKey:key cost:cost];
} }
@ -340,13 +300,6 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
return data; return data;
} }
// fallback because of https://github.com/rs/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]];
if (data) {
return data;
}
NSArray *customPaths = [self.customPaths copy]; NSArray *customPaths = [self.customPaths copy];
for (NSString *path in customPaths) { for (NSString *path in customPaths) {
NSString *filePath = [self cachePathForKey:key inPath:path]; NSString *filePath = [self cachePathForKey:key inPath:path];
@ -354,13 +307,6 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
if (imageData) { if (imageData) {
return imageData; return imageData;
} }
// fallback because of https://github.com/rs/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]];
if (imageData) {
return imageData;
}
} }
return nil; return nil;
@ -410,7 +356,7 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
@autoreleasepool { @autoreleasepool {
UIImage *diskImage = [self diskImageForKey:key]; UIImage *diskImage = [self diskImageForKey:key];
if (diskImage && self.shouldCacheImagesInMemory) { if (diskImage) {
NSUInteger cost = SDCacheCostForImage(diskImage); NSUInteger cost = SDCacheCostForImage(diskImage);
[self.memCache setObject:diskImage forKey:key cost:cost]; [self.memCache setObject:diskImage forKey:key cost:cost];
} }
@ -441,11 +387,9 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
if (key == nil) { if (key == nil) {
return; return;
} }
if (self.shouldCacheImagesInMemory) { [self.memCache removeObjectForKey:key];
[self.memCache removeObjectForKey:key];
}
if (fromDisk) { if (fromDisk) {
dispatch_async(self.ioQueue, ^{ dispatch_async(self.ioQueue, ^{
[_fileManager removeItemAtPath:[self defaultCachePathForKey:key] error:nil]; [_fileManager removeItemAtPath:[self defaultCachePathForKey:key] error:nil];
@ -530,8 +474,8 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
for (NSURL *fileURL in fileEnumerator) { for (NSURL *fileURL in fileEnumerator) {
NSDictionary *resourceValues = [fileURL resourceValuesForKeys:resourceKeys error:NULL]; NSDictionary *resourceValues = [fileURL resourceValuesForKeys:resourceKeys error:NULL];
// Skip nil or directories. // Skip directories.
if (!resourceValues || [resourceValues[NSURLIsDirectoryKey] boolValue]) { if ([resourceValues[NSURLIsDirectoryKey] boolValue]) {
continue; continue;
} }

View File

@ -14,7 +14,7 @@
#endif #endif
#if __IPHONE_OS_VERSION_MIN_REQUIRED != 20000 && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_5_0 #if __IPHONE_OS_VERSION_MIN_REQUIRED != 20000 && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_5_0
#error SDWebImage doesn't support Deployment Target version < 5.0 #error SDWebImage doesn't support Deployement Target version < 5.0
#endif #endif
#if !TARGET_OS_IPHONE #if !TARGET_OS_IPHONE

View File

@ -28,7 +28,7 @@ inline UIImage *SDScaledImageForKey(NSString *key, UIImage *image) {
} }
else { else {
if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) { if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {
CGFloat scale = 1; CGFloat scale = 1.0;
if (key.length >= 8) { if (key.length >= 8) {
NSRange range = [key rangeOfString:@"@2x."]; NSRange range = [key rangeOfString:@"@2x."];
if (range.location != NSNotFound) { if (range.location != NSNotFound) {

View File

@ -13,80 +13,60 @@
@implementation UIImage (ForceDecode) @implementation UIImage (ForceDecode)
+ (UIImage *)decodedImageWithImage:(UIImage *)image { + (UIImage *)decodedImageWithImage:(UIImage *)image {
// while downloading huge amount of images if (image.images) {
// autorelease the bitmap context // Do not decode animated images
// and all vars to help system to free memory return image;
// when there are memory warning.
// on iOS7, do not forget to call
// [[SDImageCache sharedImageCache] clearMemory];
if (image == nil) { // Prevent "CGBitmapContextCreateImage: invalid context 0x0" error
return nil;
} }
@autoreleasepool{
// do not decode animated images
if (image.images != nil) {
return image;
}
CGImageRef imageRef = image.CGImage;
CGImageAlphaInfo alpha = CGImageGetAlphaInfo(imageRef);
BOOL anyAlpha = (alpha == kCGImageAlphaFirst ||
alpha == kCGImageAlphaLast ||
alpha == kCGImageAlphaPremultipliedFirst ||
alpha == kCGImageAlphaPremultipliedLast);
if (anyAlpha) {
return image;
}
// current
CGColorSpaceModel imageColorSpaceModel = CGColorSpaceGetModel(CGImageGetColorSpace(imageRef));
CGColorSpaceRef colorspaceRef = CGImageGetColorSpace(imageRef);
BOOL unsupportedColorSpace = (imageColorSpaceModel == kCGColorSpaceModelUnknown ||
imageColorSpaceModel == kCGColorSpaceModelMonochrome ||
imageColorSpaceModel == kCGColorSpaceModelCMYK ||
imageColorSpaceModel == kCGColorSpaceModelIndexed);
if (unsupportedColorSpace) {
colorspaceRef = CGColorSpaceCreateDeviceRGB();
}
size_t width = CGImageGetWidth(imageRef);
size_t height = CGImageGetHeight(imageRef);
NSUInteger bytesPerPixel = 4;
NSUInteger bytesPerRow = bytesPerPixel * width;
NSUInteger bitsPerComponent = 8;
CGImageRef imageRef = image.CGImage;
CGSize imageSize = CGSizeMake(CGImageGetWidth(imageRef), CGImageGetHeight(imageRef));
CGRect imageRect = (CGRect){.origin = CGPointZero, .size = imageSize};
// kCGImageAlphaNone is not supported in CGBitmapContextCreate. CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
// Since the original image here has no alpha info, use kCGImageAlphaNoneSkipLast CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
// to create bitmap graphics contexts without alpha info.
CGContextRef context = CGBitmapContextCreate(NULL, int infoMask = (bitmapInfo & kCGBitmapAlphaInfoMask);
width, BOOL anyNonAlpha = (infoMask == kCGImageAlphaNone ||
height, infoMask == kCGImageAlphaNoneSkipFirst ||
bitsPerComponent, infoMask == kCGImageAlphaNoneSkipLast);
bytesPerRow,
colorspaceRef, // CGBitmapContextCreate doesn't support kCGImageAlphaNone with RGB.
kCGBitmapByteOrderDefault|kCGImageAlphaNoneSkipLast); // https://developer.apple.com/library/mac/#qa/qa1037/_index.html
if (infoMask == kCGImageAlphaNone && CGColorSpaceGetNumberOfComponents(colorSpace) > 1) {
// Draw the image into the context and retrieve the new bitmap image without alpha // Unset the old alpha info.
CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef); bitmapInfo &= ~kCGBitmapAlphaInfoMask;
CGImageRef imageRefWithoutAlpha = CGBitmapContextCreateImage(context);
UIImage *imageWithoutAlpha = [UIImage imageWithCGImage:imageRefWithoutAlpha // Set noneSkipFirst.
scale:image.scale bitmapInfo |= kCGImageAlphaNoneSkipFirst;
orientation:image.imageOrientation];
if (unsupportedColorSpace) {
CGColorSpaceRelease(colorspaceRef);
}
CGContextRelease(context);
CGImageRelease(imageRefWithoutAlpha);
return imageWithoutAlpha;
} }
// Some PNGs tell us they have alpha but only 3 components. Odd.
else if (!anyNonAlpha && CGColorSpaceGetNumberOfComponents(colorSpace) == 3) {
// Unset the old alpha info.
bitmapInfo &= ~kCGBitmapAlphaInfoMask;
bitmapInfo |= kCGImageAlphaPremultipliedFirst;
}
// It calculates the bytes-per-row based on the bitsPerComponent and width arguments.
CGContextRef context = CGBitmapContextCreate(NULL,
imageSize.width,
imageSize.height,
CGImageGetBitsPerComponent(imageRef),
0,
colorSpace,
bitmapInfo);
CGColorSpaceRelease(colorSpace);
// If failed, return undecompressed image
if (!context) return image;
CGContextDrawImage(context, imageRect, imageRef);
CGImageRef decompressedImageRef = CGBitmapContextCreateImage(context);
CGContextRelease(context);
UIImage *decompressedImage = [UIImage imageWithCGImage:decompressedImageRef scale:image.scale orientation:image.imageOrientation];
CGImageRelease(decompressedImageRef);
return decompressedImage;
} }
@end @end

View File

@ -15,7 +15,7 @@ typedef NS_OPTIONS(NSUInteger, SDWebImageDownloaderOptions) {
SDWebImageDownloaderProgressiveDownload = 1 << 1, SDWebImageDownloaderProgressiveDownload = 1 << 1,
/** /**
* By default, request prevent the use of NSURLCache. With this flag, NSURLCache * By default, request prevent the of NSURLCache. With this flag, NSURLCache
* is used with default policies. * is used with default policies.
*/ */
SDWebImageDownloaderUseNSURLCache = 1 << 2, SDWebImageDownloaderUseNSURLCache = 1 << 2,
@ -40,7 +40,7 @@ typedef NS_OPTIONS(NSUInteger, SDWebImageDownloaderOptions) {
SDWebImageDownloaderHandleCookies = 1 << 5, SDWebImageDownloaderHandleCookies = 1 << 5,
/** /**
* Enable to allow untrusted SSL certificates. * Enable to allow untrusted SSL ceriticates.
* Useful for testing purposes. Use with caution in production. * Useful for testing purposes. Use with caution in production.
*/ */
SDWebImageDownloaderAllowInvalidSSLCertificates = 1 << 6, SDWebImageDownloaderAllowInvalidSSLCertificates = 1 << 6,
@ -78,7 +78,7 @@ typedef NSDictionary *(^SDWebImageDownloaderHeadersFilterBlock)(NSURL *url, NSDi
@interface SDWebImageDownloader : NSObject @interface SDWebImageDownloader : NSObject
/** /**
* Decompressing images that are downloaded and cached can improve performance but can consume lot of memory. * Decompressing images that are downloaded and cached can improve peformance but can consume lot of memory.
* Defaults to YES. Set this to NO if you are experiencing a crash due to excessive memory consumption. * Defaults to YES. Set this to NO if you are experiencing a crash due to excessive memory consumption.
*/ */
@property (assign, nonatomic) BOOL shouldDecompressImages; @property (assign, nonatomic) BOOL shouldDecompressImages;
@ -109,11 +109,6 @@ typedef NSDictionary *(^SDWebImageDownloaderHeadersFilterBlock)(NSURL *url, NSDi
*/ */
+ (SDWebImageDownloader *)sharedDownloader; + (SDWebImageDownloader *)sharedDownloader;
/**
* Set the default URL credential to be set for request operations.
*/
@property (strong, nonatomic) NSURLCredential *urlCredential;
/** /**
* Set username * Set username
*/ */
@ -188,9 +183,4 @@ typedef NSDictionary *(^SDWebImageDownloaderHeadersFilterBlock)(NSURL *url, NSDi
*/ */
- (void)setSuspended:(BOOL)suspended; - (void)setSuspended:(BOOL)suspended;
/**
* Cancels all download operations in the queue
*/
- (void)cancelAllDownloads;
@end @end

View File

@ -13,7 +13,7 @@
static NSString *const kProgressCallbackKey = @"progress"; static NSString *const kProgressCallbackKey = @"progress";
static NSString *const kCompletedCallbackKey = @"completed"; static NSString *const kCompletedCallbackKey = @"completed";
@interface SDWebImageDownloader () <NSURLSessionTaskDelegate, NSURLSessionDataDelegate> @interface SDWebImageDownloader ()
@property (strong, nonatomic) NSOperationQueue *downloadQueue; @property (strong, nonatomic) NSOperationQueue *downloadQueue;
@property (weak, nonatomic) NSOperation *lastAddedOperation; @property (weak, nonatomic) NSOperation *lastAddedOperation;
@ -23,9 +23,6 @@ static NSString *const kCompletedCallbackKey = @"completed";
// This queue is used to serialize the handling of the network responses of all the download operation in a single queue // This queue is used to serialize the handling of the network responses of all the download operation in a single queue
@property (SDDispatchQueueSetterSementics, nonatomic) dispatch_queue_t barrierQueue; @property (SDDispatchQueueSetterSementics, nonatomic) dispatch_queue_t barrierQueue;
// The session in which data tasks will run
@property (strong, nonatomic) NSURLSession *session;
@end @end
@implementation SDWebImageDownloader @implementation SDWebImageDownloader
@ -77,26 +74,11 @@ static NSString *const kCompletedCallbackKey = @"completed";
#endif #endif
_barrierQueue = dispatch_queue_create("com.hackemist.SDWebImageDownloaderBarrierQueue", DISPATCH_QUEUE_CONCURRENT); _barrierQueue = dispatch_queue_create("com.hackemist.SDWebImageDownloaderBarrierQueue", DISPATCH_QUEUE_CONCURRENT);
_downloadTimeout = 15.0; _downloadTimeout = 15.0;
NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
sessionConfig.timeoutIntervalForRequest = _downloadTimeout;
/**
* Create the session for this task
* We send nil as delegate queue so that the session creates a serial operation queue for performing all delegate
* method calls and completion handler calls.
*/
self.session = [NSURLSession sessionWithConfiguration:sessionConfig
delegate:self
delegateQueue:nil];
} }
return self; return self;
} }
- (void)dealloc { - (void)dealloc {
[self.session invalidateAndCancel];
self.session = nil;
[self.downloadQueue cancelAllOperations]; [self.downloadQueue cancelAllOperations];
SDDispatchQueueRelease(_barrierQueue); SDDispatchQueueRelease(_barrierQueue);
} }
@ -134,7 +116,7 @@ static NSString *const kCompletedCallbackKey = @"completed";
__block SDWebImageDownloaderOperation *operation; __block SDWebImageDownloaderOperation *operation;
__weak __typeof(self)wself = self; __weak __typeof(self)wself = self;
[self addProgressCallback:progressBlock completedBlock:completedBlock forURL:url createCallback:^{ [self addProgressCallback:progressBlock andCompletedBlock:completedBlock forURL:url createCallback:^{
NSTimeInterval timeoutInterval = wself.downloadTimeout; NSTimeInterval timeoutInterval = wself.downloadTimeout;
if (timeoutInterval == 0.0) { if (timeoutInterval == 0.0) {
timeoutInterval = 15.0; timeoutInterval = 15.0;
@ -151,7 +133,6 @@ static NSString *const kCompletedCallbackKey = @"completed";
request.allHTTPHeaderFields = wself.HTTPHeaders; request.allHTTPHeaderFields = wself.HTTPHeaders;
} }
operation = [[wself.operationClass alloc] initWithRequest:request operation = [[wself.operationClass alloc] initWithRequest:request
inSession:self.session
options:options options:options
progress:^(NSInteger receivedSize, NSInteger expectedSize) { progress:^(NSInteger receivedSize, NSInteger expectedSize) {
SDWebImageDownloader *sself = wself; SDWebImageDownloader *sself = wself;
@ -161,10 +142,8 @@ static NSString *const kCompletedCallbackKey = @"completed";
callbacksForURL = [sself.URLCallbacks[url] copy]; callbacksForURL = [sself.URLCallbacks[url] copy];
}); });
for (NSDictionary *callbacks in callbacksForURL) { for (NSDictionary *callbacks in callbacksForURL) {
dispatch_async(dispatch_get_main_queue(), ^{ SDWebImageDownloaderProgressBlock callback = callbacks[kProgressCallbackKey];
SDWebImageDownloaderProgressBlock callback = callbacks[kProgressCallbackKey]; if (callback) callback(receivedSize, expectedSize);
if (callback) callback(receivedSize, expectedSize);
});
} }
} }
completed:^(UIImage *image, NSData *data, NSError *error, BOOL finished) { completed:^(UIImage *image, NSData *data, NSError *error, BOOL finished) {
@ -191,9 +170,7 @@ static NSString *const kCompletedCallbackKey = @"completed";
}]; }];
operation.shouldDecompressImages = wself.shouldDecompressImages; operation.shouldDecompressImages = wself.shouldDecompressImages;
if (wself.urlCredential) { if (wself.username && wself.password) {
operation.credential = wself.urlCredential;
} else if (wself.username && wself.password) {
operation.credential = [NSURLCredential credentialWithUser:wself.username password:wself.password persistence:NSURLCredentialPersistenceForSession]; operation.credential = [NSURLCredential credentialWithUser:wself.username password:wself.password persistence:NSURLCredentialPersistenceForSession];
} }
@ -214,7 +191,7 @@ static NSString *const kCompletedCallbackKey = @"completed";
return operation; return operation;
} }
- (void)addProgressCallback:(SDWebImageDownloaderProgressBlock)progressBlock completedBlock:(SDWebImageDownloaderCompletedBlock)completedBlock forURL:(NSURL *)url createCallback:(SDWebImageNoParamsBlock)createCallback { - (void)addProgressCallback:(SDWebImageDownloaderProgressBlock)progressBlock andCompletedBlock:(SDWebImageDownloaderCompletedBlock)completedBlock forURL:(NSURL *)url createCallback:(SDWebImageNoParamsBlock)createCallback {
// 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. // 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 (url == nil) {
if (completedBlock != nil) { if (completedBlock != nil) {
@ -248,70 +225,4 @@ static NSString *const kCompletedCallbackKey = @"completed";
[self.downloadQueue setSuspended:suspended]; [self.downloadQueue setSuspended:suspended];
} }
- (void)cancelAllDownloads {
[self.downloadQueue cancelAllOperations];
}
#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;
}
}
return returnOperation;
}
#pragma mark NSURLSessionDataDelegate
- (void)URLSession:(NSURLSession *)session
dataTask:(NSURLSessionDataTask *)dataTask
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];
[dataOperation URLSession:session dataTask:dataTask didReceiveResponse:response completionHandler:completionHandler];
}
- (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];
[dataOperation URLSession:session dataTask:dataTask didReceiveData:data];
}
- (void)URLSession:(NSURLSession *)session
dataTask:(NSURLSessionDataTask *)dataTask
willCacheResponse:(NSCachedURLResponse *)proposedResponse
completionHandler:(void (^)(NSCachedURLResponse *cachedResponse))completionHandler {
// Identify the operation that runs this task and pass it the delegate method
SDWebImageDownloaderOperation *dataOperation = [self operationWithTask:dataTask];
[dataOperation URLSession:session dataTask:dataTask willCacheResponse:proposedResponse completionHandler:completionHandler];
}
#pragma mark NSURLSessionTaskDelegate
- (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];
[dataOperation URLSession:session task:task didCompleteWithError:error];
}
- (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];
[dataOperation URLSession:session task:task didReceiveChallenge:challenge completionHandler:completionHandler];
}
@end @end

View File

@ -15,26 +15,22 @@ extern NSString *const SDWebImageDownloadReceiveResponseNotification;
extern NSString *const SDWebImageDownloadStopNotification; extern NSString *const SDWebImageDownloadStopNotification;
extern NSString *const SDWebImageDownloadFinishNotification; extern NSString *const SDWebImageDownloadFinishNotification;
@interface SDWebImageDownloaderOperation : NSOperation <SDWebImageOperation, NSURLSessionTaskDelegate, NSURLSessionDataDelegate> @interface SDWebImageDownloaderOperation : NSOperation <SDWebImageOperation>
/** /**
* The request used by the operation's task. * The request used by the operation's connection.
*/ */
@property (strong, nonatomic, readonly) NSURLRequest *request; @property (strong, nonatomic, readonly) NSURLRequest *request;
/**
* The operation's task
*/
@property (strong, nonatomic, readonly) NSURLSessionTask *dataTask;
@property (assign, nonatomic) BOOL shouldDecompressImages; @property (assign, nonatomic) BOOL shouldDecompressImages;
/** /**
* Was used to determine whether the URL connection should consult the credential storage for authenticating the connection. * Whether the URL connection should consult the credential storage for authenticating the connection. `YES` by default.
* @deprecated Not used for a couple of versions *
* This is the value that is returned in the `NSURLConnectionDelegate` method `-connectionShouldUseCredentialStorage:`.
*/ */
@property (nonatomic, assign) BOOL shouldUseCredentialStorage __deprecated_msg("Property deprecated. Does nothing. Kept only for backwards compatibility"); @property (nonatomic, assign) BOOL shouldUseCredentialStorage;
/** /**
* The credential used for authentication challenges in `-connection:didReceiveAuthenticationChallenge:`. * The credential used for authentication challenges in `-connection:didReceiveAuthenticationChallenge:`.
@ -64,7 +60,6 @@ extern NSString *const SDWebImageDownloadFinishNotification;
* @see SDWebImageDownloaderOperation * @see SDWebImageDownloaderOperation
* *
* @param request the URL request * @param request the URL request
* @param session the URL session in which this operation will run
* @param options downloader options * @param options downloader options
* @param progressBlock the block executed when a new chunk of data arrives. * @param progressBlock the block executed when a new chunk of data arrives.
* @note the progress block is executed on a background queue * @note the progress block is executed on a background queue
@ -75,32 +70,9 @@ extern NSString *const SDWebImageDownloadFinishNotification;
* @return the initialized instance * @return the initialized instance
*/ */
- (id)initWithRequest:(NSURLRequest *)request - (id)initWithRequest:(NSURLRequest *)request
inSession:(NSURLSession *)session
options:(SDWebImageDownloaderOptions)options options:(SDWebImageDownloaderOptions)options
progress:(SDWebImageDownloaderProgressBlock)progressBlock progress:(SDWebImageDownloaderProgressBlock)progressBlock
completed:(SDWebImageDownloaderCompletedBlock)completedBlock completed:(SDWebImageDownloaderCompletedBlock)completedBlock
cancelled:(SDWebImageNoParamsBlock)cancelBlock; cancelled:(SDWebImageNoParamsBlock)cancelBlock;
/**
* Initializes a `SDWebImageDownloaderOperation` object
*
* @see SDWebImageDownloaderOperation
*
* @param request the URL request
* @param options downloader options
* @param progressBlock the block executed when a new chunk of data arrives.
* @note the progress block is executed on a background queue
* @param completedBlock the block executed when the download is done.
* @note the completed block is executed on the main queue for success. If errors are found, there is a chance the block will be executed on a background queue
* @param cancelBlock the block executed if the download (operation) is cancelled
*
* @return the initialized instance. The operation will run in a separate session created for this operation
*/
- (id)initWithRequest:(NSURLRequest *)request
options:(SDWebImageDownloaderOptions)options
progress:(SDWebImageDownloaderProgressBlock)progressBlock
completed:(SDWebImageDownloaderCompletedBlock)completedBlock
cancelled:(SDWebImageNoParamsBlock)cancelBlock
__deprecated_msg("Method deprecated. Use `initWithRequest:inSession:options:progress:completed:cancelled`");
@end @end

View File

@ -17,7 +17,7 @@ NSString *const SDWebImageDownloadReceiveResponseNotification = @"SDWebImageDown
NSString *const SDWebImageDownloadStopNotification = @"SDWebImageDownloadStopNotification"; NSString *const SDWebImageDownloadStopNotification = @"SDWebImageDownloadStopNotification";
NSString *const SDWebImageDownloadFinishNotification = @"SDWebImageDownloadFinishNotification"; NSString *const SDWebImageDownloadFinishNotification = @"SDWebImageDownloadFinishNotification";
@interface SDWebImageDownloaderOperation () @interface SDWebImageDownloaderOperation () <NSURLConnectionDataDelegate>
@property (copy, nonatomic) SDWebImageDownloaderProgressBlock progressBlock; @property (copy, nonatomic) SDWebImageDownloaderProgressBlock progressBlock;
@property (copy, nonatomic) SDWebImageDownloaderCompletedBlock completedBlock; @property (copy, nonatomic) SDWebImageDownloaderCompletedBlock completedBlock;
@ -26,15 +26,7 @@ NSString *const SDWebImageDownloadFinishNotification = @"SDWebImageDownloadFinis
@property (assign, nonatomic, getter = isExecuting) BOOL executing; @property (assign, nonatomic, getter = isExecuting) BOOL executing;
@property (assign, nonatomic, getter = isFinished) BOOL finished; @property (assign, nonatomic, getter = isFinished) BOOL finished;
@property (strong, nonatomic) NSMutableData *imageData; @property (strong, nonatomic) NSMutableData *imageData;
@property (strong, nonatomic) NSURLConnection *connection;
// 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
@property (weak, nonatomic) NSURLSession *unownedSession;
// This is set if we're using not using an injected NSURLSession. We're responsible of invalidating this one
@property (strong, nonatomic) NSURLSession *ownedSession;
@property (strong, nonatomic, readwrite) NSURLSessionTask *dataTask;
@property (strong, atomic) NSThread *thread; @property (strong, atomic) NSThread *thread;
#if TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_4_0 #if TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_4_0
@ -57,24 +49,10 @@ NSString *const SDWebImageDownloadFinishNotification = @"SDWebImageDownloadFinis
progress:(SDWebImageDownloaderProgressBlock)progressBlock progress:(SDWebImageDownloaderProgressBlock)progressBlock
completed:(SDWebImageDownloaderCompletedBlock)completedBlock completed:(SDWebImageDownloaderCompletedBlock)completedBlock
cancelled:(SDWebImageNoParamsBlock)cancelBlock { cancelled:(SDWebImageNoParamsBlock)cancelBlock {
return [self initWithRequest:request
inSession:nil
options:options
progress:progressBlock
completed:completedBlock
cancelled:cancelBlock];
}
- (id)initWithRequest:(NSURLRequest *)request
inSession:(NSURLSession *)session
options:(SDWebImageDownloaderOptions)options
progress:(SDWebImageDownloaderProgressBlock)progressBlock
completed:(SDWebImageDownloaderCompletedBlock)completedBlock
cancelled:(SDWebImageNoParamsBlock)cancelBlock {
if ((self = [super init])) { if ((self = [super init])) {
_request = request; _request = request;
_shouldDecompressImages = YES; _shouldDecompressImages = YES;
_shouldUseCredentialStorage = YES;
_options = options; _options = options;
_progressBlock = [progressBlock copy]; _progressBlock = [progressBlock copy];
_completedBlock = [completedBlock copy]; _completedBlock = [completedBlock copy];
@ -82,8 +60,7 @@ NSString *const SDWebImageDownloadFinishNotification = @"SDWebImageDownloadFinis
_executing = NO; _executing = NO;
_finished = NO; _finished = NO;
_expectedSize = 0; _expectedSize = 0;
_unownedSession = session; responseFromCached = YES; // Initially wrong until `connection:willCacheResponse:` is called or not called
responseFromCached = YES; // Initially wrong until `- URLSession:dataTask:willCacheResponse:completionHandler: is called or not called
} }
return self; return self;
} }
@ -114,36 +91,36 @@ NSString *const SDWebImageDownloadFinishNotification = @"SDWebImageDownloadFinis
}]; }];
} }
#endif #endif
NSURLSession *session = self.unownedSession;
if (!self.unownedSession) {
NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
sessionConfig.timeoutIntervalForRequest = 15;
/**
* Create the session for this task
* We send nil as delegate queue so that the session creates a serial operation queue for performing all delegate
* method calls and completion handler calls.
*/
self.ownedSession = [NSURLSession sessionWithConfiguration:sessionConfig
delegate:self
delegateQueue:nil];
session = self.ownedSession;
}
self.dataTask = [session dataTaskWithRequest:self.request];
self.executing = YES; self.executing = YES;
self.connection = [[NSURLConnection alloc] initWithRequest:self.request delegate:self startImmediately:NO];
self.thread = [NSThread currentThread]; self.thread = [NSThread currentThread];
} }
[self.dataTask resume];
if (self.dataTask) { [self.connection start];
if (self.connection) {
if (self.progressBlock) { if (self.progressBlock) {
self.progressBlock(0, NSURLResponseUnknownLength); self.progressBlock(0, NSURLResponseUnknownLength);
} }
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:SDWebImageDownloadStartNotification object:self]; [[NSNotificationCenter defaultCenter] postNotificationName:SDWebImageDownloadStartNotification object:self];
}); });
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_5_1) {
// Make sure to run the runloop in our background thread so it can process downloaded data
// Note: we use a timeout to work around an issue with NSURLConnection cancel under iOS 5
// not waking up the runloop, leading to dead threads (see https://github.com/rs/SDWebImage/issues/466)
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 10, false);
}
else {
CFRunLoopRun();
}
if (!self.isFinished) {
[self.connection cancel];
[self connection:self.connection didFailWithError:[NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorTimedOut userInfo:@{NSURLErrorFailingURLErrorKey : self.request.URL}]];
}
} }
else { else {
if (self.completedBlock) { if (self.completedBlock) {
@ -178,6 +155,7 @@ NSString *const SDWebImageDownloadFinishNotification = @"SDWebImageDownloadFinis
- (void)cancelInternalAndStop { - (void)cancelInternalAndStop {
if (self.isFinished) return; if (self.isFinished) return;
[self cancelInternal]; [self cancelInternal];
CFRunLoopStop(CFRunLoopGetCurrent());
} }
- (void)cancelInternal { - (void)cancelInternal {
@ -185,8 +163,8 @@ NSString *const SDWebImageDownloadFinishNotification = @"SDWebImageDownloadFinis
[super cancel]; [super cancel];
if (self.cancelBlock) self.cancelBlock(); if (self.cancelBlock) self.cancelBlock();
if (self.dataTask) { if (self.connection) {
[self.dataTask cancel]; [self.connection cancel];
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:SDWebImageDownloadStopNotification object:self]; [[NSNotificationCenter defaultCenter] postNotificationName:SDWebImageDownloadStopNotification object:self];
}); });
@ -210,13 +188,9 @@ NSString *const SDWebImageDownloadFinishNotification = @"SDWebImageDownloadFinis
self.cancelBlock = nil; self.cancelBlock = nil;
self.completedBlock = nil; self.completedBlock = nil;
self.progressBlock = nil; self.progressBlock = nil;
self.dataTask = nil; self.connection = nil;
self.imageData = nil; self.imageData = nil;
self.thread = nil; self.thread = nil;
if (self.ownedSession) {
[self.ownedSession invalidateAndCancel];
self.ownedSession = nil;
}
} }
- (void)setFinished:(BOOL)finished { - (void)setFinished:(BOOL)finished {
@ -235,12 +209,9 @@ NSString *const SDWebImageDownloadFinishNotification = @"SDWebImageDownloadFinis
return YES; return YES;
} }
#pragma mark NSURLSessionDataDelegate #pragma mark NSURLConnection (delegate)
- (void)URLSession:(NSURLSession *)session - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
dataTask:(NSURLSessionDataTask *)dataTask
didReceiveResponse:(NSURLResponse *)response
completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler {
//'304 Not Modified' is an exceptional one //'304 Not Modified' is an exceptional one
if (![response respondsToSelector:@selector(statusCode)] || ([((NSHTTPURLResponse *)response) statusCode] < 400 && [((NSHTTPURLResponse *)response) statusCode] != 304)) { if (![response respondsToSelector:@selector(statusCode)] || ([((NSHTTPURLResponse *)response) statusCode] < 400 && [((NSHTTPURLResponse *)response) statusCode] != 304)) {
@ -249,7 +220,7 @@ didReceiveResponse:(NSURLResponse *)response
if (self.progressBlock) { if (self.progressBlock) {
self.progressBlock(0, expected); self.progressBlock(0, expected);
} }
self.imageData = [[NSMutableData alloc] initWithCapacity:expected]; self.imageData = [[NSMutableData alloc] initWithCapacity:expected];
self.response = response; self.response = response;
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
@ -264,24 +235,21 @@ didReceiveResponse:(NSURLResponse *)response
if (code == 304) { if (code == 304) {
[self cancelInternal]; [self cancelInternal];
} else { } else {
[self.dataTask cancel]; [self.connection cancel];
} }
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:SDWebImageDownloadStopNotification object:self]; [[NSNotificationCenter defaultCenter] postNotificationName:SDWebImageDownloadStopNotification object:self];
}); });
if (self.completedBlock) { if (self.completedBlock) {
self.completedBlock(nil, nil, [NSError errorWithDomain:NSURLErrorDomain code:[((NSHTTPURLResponse *)response) statusCode] userInfo:nil], YES); self.completedBlock(nil, nil, [NSError errorWithDomain:NSURLErrorDomain code:[((NSHTTPURLResponse *)response) statusCode] userInfo:nil], YES);
} }
CFRunLoopStop(CFRunLoopGetCurrent());
[self done]; [self done];
} }
if (completionHandler) {
completionHandler(NSURLSessionResponseAllow);
}
} }
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data { - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[self.imageData appendData:data]; [self.imageData appendData:data];
if ((self.options & SDWebImageDownloaderProgressiveDownload) && self.expectedSize > 0 && self.completedBlock) { if ((self.options & SDWebImageDownloaderProgressiveDownload) && self.expectedSize > 0 && self.completedBlock) {
@ -309,7 +277,7 @@ didReceiveResponse:(NSURLResponse *)response
// When we draw to Core Graphics, we lose orientation information, // When we draw to Core Graphics, we lose orientation information,
// which means the image below born of initWithCGIImage will be // which means the image below born of initWithCGIImage will be
// oriented incorrectly sometimes. (Unlike the image born of initWithData // oriented incorrectly sometimes. (Unlike the image born of initWithData
// in didCompleteWithError.) So save it here and pass it on later. // in connectionDidFinishLoading.) So save it here and pass it on later.
orientation = [[self class] orientationFromPropertyValue:(orientationValue == -1 ? 1 : orientationValue)]; orientation = [[self class] orientationFromPropertyValue:(orientationValue == -1 ? 1 : orientationValue)];
} }
@ -366,110 +334,6 @@ didReceiveResponse:(NSURLResponse *)response
} }
} }
- (void)URLSession:(NSURLSession *)session
dataTask:(NSURLSessionDataTask *)dataTask
willCacheResponse:(NSCachedURLResponse *)proposedResponse
completionHandler:(void (^)(NSCachedURLResponse *cachedResponse))completionHandler {
responseFromCached = NO; // If this method is called, it means the response wasn't read from cache
NSCachedURLResponse *cachedResponse = proposedResponse;
if (self.request.cachePolicy == NSURLRequestReloadIgnoringLocalCacheData) {
// Prevents caching of responses
cachedResponse = nil;
}
if (completionHandler) {
completionHandler(cachedResponse);
}
}
#pragma mark NSURLSessionTaskDelegate
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
@synchronized(self) {
self.thread = nil;
self.dataTask = nil;
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:SDWebImageDownloadStopNotification object:self];
if (!error) {
[[NSNotificationCenter defaultCenter] postNotificationName:SDWebImageDownloadFinishNotification object:self];
}
});
}
if (error) {
if (self.completedBlock) {
self.completedBlock(nil, nil, error, YES);
}
} else {
SDWebImageDownloaderCompletedBlock completionBlock = self.completedBlock;
if (![[NSURLCache sharedURLCache] cachedResponseForRequest:_request]) {
responseFromCached = NO;
}
if (completionBlock) {
if (self.options & SDWebImageDownloaderIgnoreCachedResponse && responseFromCached) {
completionBlock(nil, nil, nil, YES);
} else 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) {
image = [UIImage decodedImageWithImage:image];
}
}
if (CGSizeEqualToSize(image.size, CGSizeZero)) {
completionBlock(nil, nil, [NSError errorWithDomain:SDWebImageErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey : @"Downloaded image has 0 pixels"}], YES);
}
else {
completionBlock(image, self.imageData, nil, YES);
}
} else {
completionBlock(nil, nil, [NSError errorWithDomain:SDWebImageErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey : @"Image data is nil"}], YES);
}
}
}
self.completionBlock = nil;
[self done];
}
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler {
NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
__block NSURLCredential *credential = nil;
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
if (!(self.options & SDWebImageDownloaderAllowInvalidSSLCertificates)) {
disposition = NSURLSessionAuthChallengePerformDefaultHandling;
} else {
credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
disposition = NSURLSessionAuthChallengeUseCredential;
}
} else {
if ([challenge previousFailureCount] == 0) {
if (self.credential) {
credential = self.credential;
disposition = NSURLSessionAuthChallengeUseCredential;
} else {
disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge;
}
} else {
disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge;
}
}
if (completionHandler) {
completionHandler(disposition, credential);
}
}
#pragma mark Helper methods
+ (UIImageOrientation)orientationFromPropertyValue:(NSInteger)value { + (UIImageOrientation)orientationFromPropertyValue:(NSInteger)value {
switch (value) { switch (value) {
case 1: case 1:
@ -497,8 +361,106 @@ didReceiveResponse:(NSURLResponse *)response
return SDScaledImageForKey(key, image); return SDScaledImageForKey(key, image);
} }
- (void)connectionDidFinishLoading:(NSURLConnection *)aConnection {
SDWebImageDownloaderCompletedBlock completionBlock = self.completedBlock;
@synchronized(self) {
CFRunLoopStop(CFRunLoopGetCurrent());
self.thread = nil;
self.connection = nil;
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:SDWebImageDownloadStopNotification object:self];
[[NSNotificationCenter defaultCenter] postNotificationName:SDWebImageDownloadFinishNotification object:self];
});
}
if (![[NSURLCache sharedURLCache] cachedResponseForRequest:_request]) {
responseFromCached = NO;
}
if (completionBlock) {
if (self.options & SDWebImageDownloaderIgnoreCachedResponse && responseFromCached) {
completionBlock(nil, nil, nil, YES);
} else 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) {
image = [UIImage decodedImageWithImage:image];
}
}
if (CGSizeEqualToSize(image.size, CGSizeZero)) {
completionBlock(nil, nil, [NSError errorWithDomain:SDWebImageErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey : @"Downloaded image has 0 pixels"}], YES);
}
else {
completionBlock(image, self.imageData, nil, YES);
}
} else {
completionBlock(nil, nil, [NSError errorWithDomain:SDWebImageErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey : @"Image data is nil"}], YES);
}
}
self.completionBlock = nil;
[self done];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
@synchronized(self) {
CFRunLoopStop(CFRunLoopGetCurrent());
self.thread = nil;
self.connection = nil;
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:SDWebImageDownloadStopNotification object:self];
});
}
if (self.completedBlock) {
self.completedBlock(nil, nil, error, YES);
}
self.completionBlock = nil;
[self done];
}
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse {
responseFromCached = NO; // If this method is called, it means the response wasn't read from cache
if (self.request.cachePolicy == NSURLRequestReloadIgnoringLocalCacheData) {
// Prevents caching of responses
return nil;
}
else {
return cachedResponse;
}
}
- (BOOL)shouldContinueWhenAppEntersBackground { - (BOOL)shouldContinueWhenAppEntersBackground {
return self.options & SDWebImageDownloaderContinueInBackground; return self.options & SDWebImageDownloaderContinueInBackground;
} }
- (BOOL)connectionShouldUseCredentialStorage:(NSURLConnection __unused *)connection {
return self.shouldUseCredentialStorage;
}
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge{
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
if (!(self.options & SDWebImageDownloaderAllowInvalidSSLCertificates) &&
[challenge.sender respondsToSelector:@selector(performDefaultHandlingForAuthenticationChallenge:)]) {
[challenge.sender performDefaultHandlingForAuthenticationChallenge:challenge];
} else {
NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
}
} else {
if ([challenge previousFailureCount] == 0) {
if (self.credential) {
[[challenge sender] useCredential:self.credential forAuthenticationChallenge:challenge];
} else {
[[challenge sender] continueWithoutCredentialForAuthenticationChallenge:challenge];
}
} else {
[[challenge sender] continueWithoutCredentialForAuthenticationChallenge:challenge];
}
}
}
@end @end

View File

@ -41,7 +41,7 @@ typedef NS_OPTIONS(NSUInteger, SDWebImageOptions) {
* This option helps deal with images changing behind the same request URL, e.g. Facebook graph api profile pics. * This option helps deal with images changing behind the same request URL, e.g. Facebook graph api profile pics.
* If a cached image is refreshed, the completion block is called once with the cached image and again with the final image. * If a cached image is refreshed, the completion block is called once with the cached image and again with the final image.
* *
* Use this flag only if you can't make your URLs static with embedded cache busting parameter. * Use this flag only if you can't make your URLs static with embeded cache busting parameter.
*/ */
SDWebImageRefreshCached = 1 << 4, SDWebImageRefreshCached = 1 << 4,
@ -58,14 +58,15 @@ typedef NS_OPTIONS(NSUInteger, SDWebImageOptions) {
SDWebImageHandleCookies = 1 << 6, SDWebImageHandleCookies = 1 << 6,
/** /**
* Enable to allow untrusted SSL certificates. * Enable to allow untrusted SSL ceriticates.
* Useful for testing purposes. Use with caution in production. * Useful for testing purposes. Use with caution in production.
*/ */
SDWebImageAllowInvalidSSLCertificates = 1 << 7, SDWebImageAllowInvalidSSLCertificates = 1 << 7,
/** /**
* By default, images are loaded in the order in which they were queued. This flag moves them to * By default, image are loaded in the order they were queued. This flag move them to
* the front of the queue. * the front of the queue and is loaded immediately instead of waiting for the current queue to be loaded (which
* could take a while).
*/ */
SDWebImageHighPriority = 1 << 8, SDWebImageHighPriority = 1 << 8,
@ -138,14 +139,14 @@ typedef NSString *(^SDWebImageCacheKeyFilterBlock)(NSURL *url);
* @code * @code
SDWebImageManager *manager = [SDWebImageManager sharedManager]; SDWebImageManager *manager = [SDWebImageManager sharedManager];
[manager downloadImageWithURL:imageURL [manager loadImageWithURL:imageURL
options:0 options:0
progress:nil progress:nil
completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
if (image) { if (image) {
// do something with image // do something with image
} }
}]; }];
* @endcode * @endcode
*/ */
@ -181,12 +182,6 @@ SDWebImageManager *manager = [SDWebImageManager sharedManager];
*/ */
+ (SDWebImageManager *)sharedManager; + (SDWebImageManager *)sharedManager;
/**
* Allows to specify instance of cache and image downloader used with image manager.
* @return new instance of `SDWebImageManager` with specified cache and downloader.
*/
- (instancetype)initWithCache:(SDImageCache *)cache downloader:(SDWebImageDownloader *)downloader;
/** /**
* Downloads the image at the given URL if not present in cache or return the cached version otherwise. * Downloads the image at the given URL if not present in cache or return the cached version otherwise.
* *
@ -200,19 +195,19 @@ SDWebImageManager *manager = [SDWebImageManager sharedManager];
* This block has no return value and takes the requested UIImage as first parameter. * This block has no return value and takes the requested UIImage as first parameter.
* In case of error the image parameter is nil and the second parameter may contain an NSError. * In case of error the image parameter is nil and the second parameter may contain an NSError.
* *
* The third parameter is an `SDImageCacheType` enum indicating if the image was retrieved from the local cache * The third parameter is an `SDImageCacheType` enum indicating if the image was retrived from the local cache
* or from the memory cache or from the network. * or from the memory cache or from the network.
* *
* The last parameter is set to NO when the SDWebImageProgressiveDownload option is used and the image is * The last parameter is set to NO when the SDWebImageProgressiveDownload option is used and the image is
* downloading. This block is thus called repeatedly with a partial image. When image is fully downloaded, the * downloading. This block is thus called repetidly with a partial image. When image is fully downloaded, the
* block is called a last time with the full image and the last parameter set to YES. * block is called a last time with the full image and the last parameter set to YES.
* *
* @return Returns an NSObject conforming to SDWebImageOperation. Should be an instance of SDWebImageDownloaderOperation * @return Returns an NSObject conforming to SDWebImageOperation. Should be an instance of SDWebImageDownloaderOperation
*/ */
- (id <SDWebImageOperation>)downloadImageWithURL:(NSURL *)url - (id <SDWebImageOperation>)loadImageWithURL:(NSURL *)url
options:(SDWebImageOptions)options options:(SDWebImageOptions)options
progress:(SDWebImageDownloaderProgressBlock)progressBlock progress:(SDWebImageDownloaderProgressBlock)progressBlock
completed:(SDWebImageCompletionWithFinishedBlock)completedBlock; completed:(SDWebImageCompletionWithFinishedBlock)completedBlock;
/** /**
* Saves image to cache for given URL * Saves image to cache for given URL
@ -225,7 +220,7 @@ SDWebImageManager *manager = [SDWebImageManager sharedManager];
- (void)saveImageToCache:(UIImage *)image forURL:(NSURL *)url; - (void)saveImageToCache:(UIImage *)image forURL:(NSURL *)url;
/** /**
* Cancel all current operations * Cancel all current opreations
*/ */
- (void)cancelAll; - (void)cancelAll;
@ -281,24 +276,3 @@ SDWebImageManager *manager = [SDWebImageManager sharedManager];
- (NSString *)cacheKeyForURL:(NSURL *)url; - (NSString *)cacheKeyForURL:(NSURL *)url;
@end @end
#pragma mark - Deprecated
typedef void(^SDWebImageCompletedBlock)(UIImage *image, NSError *error, SDImageCacheType cacheType) __deprecated_msg("Block type deprecated. Use `SDWebImageCompletionBlock`");
typedef void(^SDWebImageCompletedWithFinishedBlock)(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished) __deprecated_msg("Block type deprecated. Use `SDWebImageCompletionWithFinishedBlock`");
@interface SDWebImageManager (Deprecated)
/**
* Downloads the image at the given URL if not present in cache or return the cached version otherwise.
*
* @deprecated This method has been deprecated. Use `downloadImageWithURL:options:progress:completed:`
*/
- (id <SDWebImageOperation>)downloadWithURL:(NSURL *)url
options:(SDWebImageOptions)options
progress:(SDWebImageDownloaderProgressBlock)progressBlock
completed:(SDWebImageCompletedWithFinishedBlock)completedBlock __deprecated_msg("Method deprecated. Use `downloadImageWithURL:options:progress:completed:`");
@end

View File

@ -37,30 +37,25 @@
return instance; return instance;
} }
- (instancetype)init { - (id)init {
SDImageCache *cache = [SDImageCache sharedImageCache];
SDWebImageDownloader *downloader = [SDWebImageDownloader sharedDownloader];
return [self initWithCache:cache downloader:downloader];
}
- (instancetype)initWithCache:(SDImageCache *)cache downloader:(SDWebImageDownloader *)downloader {
if ((self = [super init])) { if ((self = [super init])) {
_imageCache = cache; _imageCache = [self createCache];
_imageDownloader = downloader; _imageDownloader = [SDWebImageDownloader sharedDownloader];
_failedURLs = [NSMutableSet new]; _failedURLs = [NSMutableSet new];
_runningOperations = [NSMutableArray new]; _runningOperations = [NSMutableArray new];
} }
return self; return self;
} }
- (SDImageCache *)createCache {
return [SDImageCache sharedImageCache];
}
- (NSString *)cacheKeyForURL:(NSURL *)url { - (NSString *)cacheKeyForURL:(NSURL *)url {
if (!url) {
return @"";
}
if (self.cacheKeyFilter) { if (self.cacheKeyFilter) {
return self.cacheKeyFilter(url); return self.cacheKeyFilter(url);
} else { }
else {
return [url absoluteString]; return [url absoluteString];
} }
} }
@ -112,7 +107,7 @@
}]; }];
} }
- (id <SDWebImageOperation>)downloadImageWithURL:(NSURL *)url - (id <SDWebImageOperation>)loadImageWithURL:(NSURL *)url
options:(SDWebImageOptions)options options:(SDWebImageOptions)options
progress:(SDWebImageDownloaderProgressBlock)progressBlock progress:(SDWebImageDownloaderProgressBlock)progressBlock
completed:(SDWebImageCompletionWithFinishedBlock)completedBlock { completed:(SDWebImageCompletionWithFinishedBlock)completedBlock {
@ -138,7 +133,7 @@
isFailedUrl = [self.failedURLs containsObject:url]; isFailedUrl = [self.failedURLs containsObject:url];
} }
if (url.absoluteString.length == 0 || (!(options & SDWebImageRetryFailed) && isFailedUrl)) { if (!url || (!(options & SDWebImageRetryFailed) && isFailedUrl)) {
dispatch_main_sync_safe(^{ dispatch_main_sync_safe(^{
NSError *error = [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorFileDoesNotExist userInfo:nil]; NSError *error = [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorFileDoesNotExist userInfo:nil];
completedBlock(nil, error, SDImageCacheTypeNone, YES, url); completedBlock(nil, error, SDImageCacheTypeNone, YES, url);
@ -163,7 +158,7 @@
if ((!image || options & SDWebImageRefreshCached) && (![self.delegate respondsToSelector:@selector(imageManager:shouldDownloadImageForURL:)] || [self.delegate imageManager:self shouldDownloadImageForURL:url])) { if ((!image || options & SDWebImageRefreshCached) && (![self.delegate respondsToSelector:@selector(imageManager:shouldDownloadImageForURL:)] || [self.delegate imageManager:self shouldDownloadImageForURL:url])) {
if (image && options & SDWebImageRefreshCached) { if (image && options & SDWebImageRefreshCached) {
dispatch_main_sync_safe(^{ dispatch_main_sync_safe(^{
// If image was found in the cache but SDWebImageRefreshCached is provided, notify about the cached image // If image was found in the cache bug SDWebImageRefreshCached is provided, notify about the cached image
// AND try to re-download it in order to let a chance to NSURLCache to refresh it from server. // AND try to re-download it in order to let a chance to NSURLCache to refresh it from server.
completedBlock(image, nil, cacheType, YES, url); completedBlock(image, nil, cacheType, YES, url);
}); });
@ -185,26 +180,21 @@
downloaderOptions |= SDWebImageDownloaderIgnoreCachedResponse; downloaderOptions |= SDWebImageDownloaderIgnoreCachedResponse;
} }
id <SDWebImageOperation> subOperation = [self.imageDownloader downloadImageWithURL:url options:downloaderOptions progress:progressBlock completed:^(UIImage *downloadedImage, NSData *data, NSError *error, BOOL finished) { id <SDWebImageOperation> subOperation = [self.imageDownloader downloadImageWithURL:url options:downloaderOptions progress:progressBlock completed:^(UIImage *downloadedImage, NSData *data, NSError *error, BOOL finished) {
__strong __typeof(weakOperation) strongOperation = weakOperation; if (weakOperation.isCancelled) {
if (!strongOperation || strongOperation.isCancelled) {
// Do nothing if the operation was cancelled // Do nothing if the operation was cancelled
// See #699 for more details // See #699 for more details
// if we would call the completedBlock, there could be a race condition between this block and another completedBlock for the same object, so if this one is called second, we will overwrite the new data // if we would call the completedBlock, there could be a race condition between this block and another completedBlock for the same object, so if this one is called second, we will overwrite the new data
} }
else if (error) { else if (error) {
dispatch_main_sync_safe(^{ dispatch_main_sync_safe(^{
if (strongOperation && !strongOperation.isCancelled) { if (!weakOperation.isCancelled) {
completedBlock(nil, error, SDImageCacheTypeNone, finished, url); completedBlock(nil, error, SDImageCacheTypeNone, finished, url);
} }
}); });
if ( error.code != NSURLErrorNotConnectedToInternet BOOL shouldBeFailedURLAlliOSVersion = (error.code != NSURLErrorNotConnectedToInternet && error.code != NSURLErrorCancelled && error.code != NSURLErrorTimedOut);
&& error.code != NSURLErrorCancelled BOOL shouldBeFailedURLiOS7 = (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1 && error.code != NSURLErrorInternationalRoamingOff && error.code != NSURLErrorCallIsActive && error.code != NSURLErrorDataNotAllowed);
&& error.code != NSURLErrorTimedOut if (shouldBeFailedURLAlliOSVersion || shouldBeFailedURLiOS7) {
&& error.code != NSURLErrorInternationalRoamingOff
&& error.code != NSURLErrorDataNotAllowed
&& error.code != NSURLErrorCannotFindHost
&& error.code != NSURLErrorCannotConnectToHost) {
@synchronized (self.failedURLs) { @synchronized (self.failedURLs) {
[self.failedURLs addObject:url]; [self.failedURLs addObject:url];
} }
@ -232,7 +222,7 @@
} }
dispatch_main_sync_safe(^{ dispatch_main_sync_safe(^{
if (strongOperation && !strongOperation.isCancelled) { if (!weakOperation.isCancelled) {
completedBlock(transformedImage, nil, SDImageCacheTypeNone, finished, url); completedBlock(transformedImage, nil, SDImageCacheTypeNone, finished, url);
} }
}); });
@ -244,7 +234,7 @@
} }
dispatch_main_sync_safe(^{ dispatch_main_sync_safe(^{
if (strongOperation && !strongOperation.isCancelled) { if (!weakOperation.isCancelled) {
completedBlock(downloadedImage, nil, SDImageCacheTypeNone, finished, url); completedBlock(downloadedImage, nil, SDImageCacheTypeNone, finished, url);
} }
}); });
@ -253,9 +243,7 @@
if (finished) { if (finished) {
@synchronized (self.runningOperations) { @synchronized (self.runningOperations) {
if (strongOperation) { [self.runningOperations removeObject:operation];
[self.runningOperations removeObject:strongOperation];
}
} }
} }
}]; }];
@ -263,17 +251,13 @@
[subOperation cancel]; [subOperation cancel];
@synchronized (self.runningOperations) { @synchronized (self.runningOperations) {
__strong __typeof(weakOperation) strongOperation = weakOperation; [self.runningOperations removeObject:weakOperation];
if (strongOperation) {
[self.runningOperations removeObject:strongOperation];
}
} }
}; };
} }
else if (image) { else if (image) {
dispatch_main_sync_safe(^{ dispatch_main_sync_safe(^{
__strong __typeof(weakOperation) strongOperation = weakOperation; if (!weakOperation.isCancelled) {
if (strongOperation && !strongOperation.isCancelled) {
completedBlock(image, nil, cacheType, YES, url); completedBlock(image, nil, cacheType, YES, url);
} }
}); });
@ -284,8 +268,7 @@
else { else {
// Image not in cache and download disallowed by delegate // Image not in cache and download disallowed by delegate
dispatch_main_sync_safe(^{ dispatch_main_sync_safe(^{
__strong __typeof(weakOperation) strongOperation = weakOperation; if (!weakOperation.isCancelled) {
if (strongOperation && !weakOperation.isCancelled) {
completedBlock(nil, nil, SDImageCacheTypeNone, YES, url); completedBlock(nil, nil, SDImageCacheTypeNone, YES, url);
} }
}); });
@ -314,11 +297,7 @@
} }
- (BOOL)isRunning { - (BOOL)isRunning {
BOOL isRunning = NO; return self.runningOperations.count > 0;
@synchronized(self.runningOperations) {
isRunning = (self.runningOperations.count > 0);
}
return isRunning;
} }
@end @end
@ -355,21 +334,3 @@
} }
@end @end
@implementation SDWebImageManager (Deprecated)
// deprecated method, uses the non deprecated method
// adapter for the completion block
- (id <SDWebImageOperation>)downloadWithURL:(NSURL *)url options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletedWithFinishedBlock)completedBlock {
return [self downloadImageWithURL:url
options:options
progress:progressBlock
completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
if (completedBlock) {
completedBlock(image, error, cacheType, finished);
}
}];
}
@end

View File

@ -70,11 +70,6 @@ typedef void(^SDWebImagePrefetcherCompletionBlock)(NSUInteger noOfFinishedUrls,
*/ */
+ (SDWebImagePrefetcher *)sharedImagePrefetcher; + (SDWebImagePrefetcher *)sharedImagePrefetcher;
/**
* Allows you to instantiate a prefetcher with any arbitrary image manager.
*/
- (id)initWithImageManager:(SDWebImageManager *)manager;
/** /**
* Assign list of URLs to let SDWebImagePrefetcher to queue the prefetching, * Assign list of URLs to let SDWebImagePrefetcher to queue the prefetching,
* currently one image is downloaded at a time, * currently one image is downloaded at a time,

View File

@ -8,6 +8,10 @@
#import "SDWebImagePrefetcher.h" #import "SDWebImagePrefetcher.h"
#if (!defined(DEBUG) && !defined (SD_VERBOSE)) || defined(SD_LOG_NONE)
#define NSLog(...)
#endif
@interface SDWebImagePrefetcher () @interface SDWebImagePrefetcher ()
@property (strong, nonatomic) SDWebImageManager *manager; @property (strong, nonatomic) SDWebImageManager *manager;
@ -33,12 +37,8 @@
} }
- (id)init { - (id)init {
return [self initWithImageManager:[SDWebImageManager new]];
}
- (id)initWithImageManager:(SDWebImageManager *)manager {
if ((self = [super init])) { if ((self = [super init])) {
_manager = manager; _manager = [SDWebImageManager new];
_options = SDWebImageLowPriority; _options = SDWebImageLowPriority;
_prefetcherQueue = dispatch_get_main_queue(); _prefetcherQueue = dispatch_get_main_queue();
self.maxConcurrentDownloads = 3; self.maxConcurrentDownloads = 3;
@ -57,7 +57,7 @@
- (void)startPrefetchingAtIndex:(NSUInteger)index { - (void)startPrefetchingAtIndex:(NSUInteger)index {
if (index >= self.prefetchURLs.count) return; if (index >= self.prefetchURLs.count) return;
self.requestedCount++; self.requestedCount++;
[self.manager downloadImageWithURL:self.prefetchURLs[index] options:self.options progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { [self.manager loadImageWithURL:self.prefetchURLs[index] options:self.options progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
if (!finished) return; if (!finished) return;
self.finishedCount++; self.finishedCount++;
@ -65,11 +65,14 @@
if (self.progressBlock) { if (self.progressBlock) {
self.progressBlock(self.finishedCount,[self.prefetchURLs count]); self.progressBlock(self.finishedCount,[self.prefetchURLs count]);
} }
NSLog(@"Prefetched %@ out of %@", @(self.finishedCount), @(self.prefetchURLs.count));
} }
else { else {
if (self.progressBlock) { if (self.progressBlock) {
self.progressBlock(self.finishedCount,[self.prefetchURLs count]); self.progressBlock(self.finishedCount,[self.prefetchURLs count]);
} }
NSLog(@"Prefetched %@ out of %@ (Failed)", @(self.finishedCount), @(self.prefetchURLs.count));
// Add last failed // Add last failed
self.skippedCount++; self.skippedCount++;
} }
@ -78,13 +81,14 @@
didPrefetchURL:self.prefetchURLs[index] didPrefetchURL:self.prefetchURLs[index]
finishedCount:self.finishedCount finishedCount:self.finishedCount
totalCount:self.prefetchURLs.count totalCount:self.prefetchURLs.count
]; ];
} }
if (self.prefetchURLs.count > self.requestedCount) { if (self.prefetchURLs.count > self.requestedCount) {
dispatch_async(self.prefetcherQueue, ^{ dispatch_async(self.prefetcherQueue, ^{
[self startPrefetchingAtIndex:self.requestedCount]; [self startPrefetchingAtIndex:self.requestedCount];
}); });
} else if (self.finishedCount == self.requestedCount) { }
else if (self.finishedCount == self.requestedCount) {
[self reportStatus]; [self reportStatus];
if (self.completionBlock) { if (self.completionBlock) {
self.completionBlock(self.finishedCount, self.skippedCount); self.completionBlock(self.finishedCount, self.skippedCount);
@ -97,11 +101,12 @@
- (void)reportStatus { - (void)reportStatus {
NSUInteger total = [self.prefetchURLs count]; NSUInteger total = [self.prefetchURLs count];
NSLog(@"Finished prefetching (%@ successful, %@ skipped, timeElasped %.2f)", @(total - self.skippedCount), @(self.skippedCount), CFAbsoluteTimeGetCurrent() - self.startedTime);
if ([self.delegate respondsToSelector:@selector(imagePrefetcher:didFinishWithTotalCount:skippedCount:)]) { if ([self.delegate respondsToSelector:@selector(imagePrefetcher:didFinishWithTotalCount:skippedCount:)]) {
[self.delegate imagePrefetcher:self [self.delegate imagePrefetcher:self
didFinishWithTotalCount:(total - self.skippedCount) didFinishWithTotalCount:(total - self.skippedCount)
skippedCount:self.skippedCount skippedCount:self.skippedCount
]; ];
} }
} }
@ -116,11 +121,11 @@
self.completionBlock = completionBlock; self.completionBlock = completionBlock;
self.progressBlock = progressBlock; self.progressBlock = progressBlock;
if (urls.count == 0) { if(urls.count == 0){
if (completionBlock) { if(completionBlock){
completionBlock(0,0); completionBlock(0,0);
} }
} else { }else{
// Starts prefetching from the very first image on the list with the max allowed concurrency // Starts prefetching from the very first image on the list with the max allowed concurrency
NSUInteger listCount = self.prefetchURLs.count; NSUInteger listCount = self.prefetchURLs.count;
for (NSUInteger i = 0; i < self.maxConcurrentDownloads && self.requestedCount < listCount; i++) { for (NSUInteger i = 0; i < self.maxConcurrentDownloads && self.requestedCount < listCount; i++) {

View File

@ -70,7 +70,7 @@
* @param completedBlock A block called when operation has been completed. This block has no return value * @param completedBlock A block called when operation has been completed. This block has no return value
* and takes the requested UIImage as first parameter. In case of error the image parameter * and takes the requested UIImage as first parameter. In case of error the image parameter
* is nil and the second parameter may contain an NSError. The third parameter is a Boolean * is nil and the second parameter may contain an NSError. The third parameter is a Boolean
* indicating if the image was retrieved from the local cache or from the network. * indicating if the image was retrived from the local cache or from the network.
* The fourth parameter is the original image url. * The fourth parameter is the original image url.
*/ */
- (void)sd_setImageWithURL:(NSURL *)url forState:(UIControlState)state completed:(SDWebImageCompletionBlock)completedBlock; - (void)sd_setImageWithURL:(NSURL *)url forState:(UIControlState)state completed:(SDWebImageCompletionBlock)completedBlock;
@ -86,7 +86,7 @@
* @param completedBlock A block called when operation has been completed. This block has no return value * @param completedBlock A block called when operation has been completed. This block has no return value
* and takes the requested UIImage as first parameter. In case of error the image parameter * and takes the requested UIImage as first parameter. In case of error the image parameter
* is nil and the second parameter may contain an NSError. The third parameter is a Boolean * is nil and the second parameter may contain an NSError. The third parameter is a Boolean
* indicating if the image was retrieved from the local cache or from the network. * indicating if the image was retrived from the local cache or from the network.
* The fourth parameter is the original image url. * The fourth parameter is the original image url.
*/ */
- (void)sd_setImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletionBlock)completedBlock; - (void)sd_setImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletionBlock)completedBlock;
@ -103,7 +103,7 @@
* @param completedBlock A block called when operation has been completed. This block has no return value * @param completedBlock A block called when operation has been completed. This block has no return value
* and takes the requested UIImage as first parameter. In case of error the image parameter * and takes the requested UIImage as first parameter. In case of error the image parameter
* is nil and the second parameter may contain an NSError. The third parameter is a Boolean * is nil and the second parameter may contain an NSError. The third parameter is a Boolean
* indicating if the image was retrieved from the local cache or from the network. * indicating if the image was retrived from the local cache or from the network.
* The fourth parameter is the original image url. * The fourth parameter is the original image url.
*/ */
- (void)sd_setImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock; - (void)sd_setImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock;
@ -152,7 +152,7 @@
* @param completedBlock A block called when operation has been completed. This block has no return value * @param completedBlock A block called when operation has been completed. This block has no return value
* and takes the requested UIImage as first parameter. In case of error the image parameter * and takes the requested UIImage as first parameter. In case of error the image parameter
* is nil and the second parameter may contain an NSError. The third parameter is a Boolean * is nil and the second parameter may contain an NSError. The third parameter is a Boolean
* indicating if the image was retrieved from the local cache or from the network. * indicating if the image was retrived from the local cache or from the network.
* The fourth parameter is the original image url. * The fourth parameter is the original image url.
*/ */
- (void)sd_setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state completed:(SDWebImageCompletionBlock)completedBlock; - (void)sd_setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state completed:(SDWebImageCompletionBlock)completedBlock;
@ -168,7 +168,7 @@
* @param completedBlock A block called when operation has been completed. This block has no return value * @param completedBlock A block called when operation has been completed. This block has no return value
* and takes the requested UIImage as first parameter. In case of error the image parameter * and takes the requested UIImage as first parameter. In case of error the image parameter
* is nil and the second parameter may contain an NSError. The third parameter is a Boolean * is nil and the second parameter may contain an NSError. The third parameter is a Boolean
* indicating if the image was retrieved from the local cache or from the network. * indicating if the image was retrived from the local cache or from the network.
* The fourth parameter is the original image url. * The fourth parameter is the original image url.
*/ */
- (void)sd_setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletionBlock)completedBlock; - (void)sd_setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletionBlock)completedBlock;
@ -184,7 +184,7 @@
* @param completedBlock A block called when operation has been completed. This block has no return value * @param completedBlock A block called when operation has been completed. This block has no return value
* and takes the requested UIImage as first parameter. In case of error the image parameter * and takes the requested UIImage as first parameter. In case of error the image parameter
* is nil and the second parameter may contain an NSError. The third parameter is a Boolean * is nil and the second parameter may contain an NSError. The third parameter is a Boolean
* indicating if the image was retrieved from the local cache or from the network. * indicating if the image was retrived from the local cache or from the network.
* The fourth parameter is the original image url. * The fourth parameter is the original image url.
*/ */
- (void)sd_setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock; - (void)sd_setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock;
@ -200,30 +200,3 @@
- (void)sd_cancelBackgroundImageLoadForState:(UIControlState)state; - (void)sd_cancelBackgroundImageLoadForState:(UIControlState)state;
@end @end
@interface UIButton (WebCacheDeprecated)
- (NSURL *)currentImageURL __deprecated_msg("Use `sd_currentImageURL`");
- (NSURL *)imageURLForState:(UIControlState)state __deprecated_msg("Use `sd_imageURLForState:`");
- (void)setImageWithURL:(NSURL *)url forState:(UIControlState)state __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:forState:`");
- (void)setImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:forState:placeholderImage:`");
- (void)setImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:forState:placeholderImage:options:`");
- (void)setImageWithURL:(NSURL *)url forState:(UIControlState)state completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:forState:completed:`");
- (void)setImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:forState:placeholderImage:completed:`");
- (void)setImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:forState:placeholderImage:options:completed:`");
- (void)setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state __deprecated_msg("Method deprecated. Use `sd_setBackgroundImageWithURL:forState:`");
- (void)setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder __deprecated_msg("Method deprecated. Use `sd_setBackgroundImageWithURL:forState:placeholderImage:`");
- (void)setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options __deprecated_msg("Method deprecated. Use `sd_setBackgroundImageWithURL:forState:placeholderImage:options:`");
- (void)setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setBackgroundImageWithURL:forState:completed:`");
- (void)setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setBackgroundImageWithURL:forState:placeholderImage:completed:`");
- (void)setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setBackgroundImageWithURL:forState:placeholderImage:options:completed:`");
- (void)cancelCurrentImageLoad __deprecated_msg("Use `sd_cancelImageLoadForState:`");
- (void)cancelBackgroundImageLoadForState:(UIControlState)state __deprecated_msg("Use `sd_cancelBackgroundImageLoadForState:`");
@end

View File

@ -57,8 +57,8 @@ static char imageURLStorageKey;
[self.imageURLStorage removeObjectForKey:@(state)]; [self.imageURLStorage removeObjectForKey:@(state)];
dispatch_main_async_safe(^{ dispatch_main_async_safe(^{
NSError *error = [NSError errorWithDomain:SDWebImageErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey : @"Trying to load a nil url"}];
if (completedBlock) { if (completedBlock) {
NSError *error = [NSError errorWithDomain:SDWebImageErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey : @"Trying to load a nil url"}];
completedBlock(nil, error, SDImageCacheTypeNone, url); completedBlock(nil, error, SDImageCacheTypeNone, url);
} }
}); });
@ -69,17 +69,12 @@ static char imageURLStorageKey;
self.imageURLStorage[@(state)] = url; self.imageURLStorage[@(state)] = url;
__weak __typeof(self)wself = self; __weak __typeof(self)wself = self;
id <SDWebImageOperation> operation = [SDWebImageManager.sharedManager downloadImageWithURL:url options:options progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { id <SDWebImageOperation> operation = [SDWebImageManager.sharedManager loadImageWithURL:url options:options progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
if (!wself) return; if (!wself) return;
dispatch_main_sync_safe(^{ dispatch_main_sync_safe(^{
__strong UIButton *sself = wself; __strong UIButton *sself = wself;
if (!sself) return; if (!sself) return;
if (image && (options & SDWebImageAvoidAutoSetImage) && completedBlock) if (image) {
{
completedBlock(image, error, cacheType, url);
return;
}
else if (image) {
[sself setImage:image forState:state]; [sself setImage:image forState:state];
} }
if (completedBlock && finished) { if (completedBlock && finished) {
@ -111,23 +106,18 @@ static char imageURLStorageKey;
} }
- (void)sd_setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock { - (void)sd_setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock {
[self sd_cancelBackgroundImageLoadForState:state]; [self sd_cancelImageLoadForState:state];
[self setBackgroundImage:placeholder forState:state]; [self setBackgroundImage:placeholder forState:state];
if (url) { if (url) {
__weak __typeof(self)wself = self; __weak __typeof(self)wself = self;
id <SDWebImageOperation> operation = [SDWebImageManager.sharedManager downloadImageWithURL:url options:options progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { id <SDWebImageOperation> operation = [SDWebImageManager.sharedManager loadImageWithURL:url options:options progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
if (!wself) return; if (!wself) return;
dispatch_main_sync_safe(^{ dispatch_main_sync_safe(^{
__strong UIButton *sself = wself; __strong UIButton *sself = wself;
if (!sself) return; if (!sself) return;
if (image && (options & SDWebImageAvoidAutoSetImage) && completedBlock) if (image) {
{
completedBlock(image, error, cacheType, url);
return;
}
else if (image) {
[sself setBackgroundImage:image forState:state]; [sself setBackgroundImage:image forState:state];
} }
if (completedBlock && finished) { if (completedBlock && finished) {
@ -174,97 +164,3 @@ static char imageURLStorageKey;
} }
@end @end
@implementation UIButton (WebCacheDeprecated)
- (NSURL *)currentImageURL {
return [self sd_currentImageURL];
}
- (NSURL *)imageURLForState:(UIControlState)state {
return [self sd_imageURLForState:state];
}
- (void)setImageWithURL:(NSURL *)url forState:(UIControlState)state {
[self sd_setImageWithURL:url forState:state placeholderImage:nil options:0 completed:nil];
}
- (void)setImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder {
[self sd_setImageWithURL:url forState:state placeholderImage:placeholder options:0 completed:nil];
}
- (void)setImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options {
[self sd_setImageWithURL:url forState:state placeholderImage:placeholder options:options completed:nil];
}
- (void)setImageWithURL:(NSURL *)url forState:(UIControlState)state completed:(SDWebImageCompletedBlock)completedBlock {
[self sd_setImageWithURL:url forState:state placeholderImage:nil options:0 completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
if (completedBlock) {
completedBlock(image, error, cacheType);
}
}];
}
- (void)setImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletedBlock)completedBlock {
[self sd_setImageWithURL:url forState:state placeholderImage:placeholder options:0 completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
if (completedBlock) {
completedBlock(image, error, cacheType);
}
}];
}
- (void)setImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletedBlock)completedBlock {
[self sd_setImageWithURL:url forState:state placeholderImage:placeholder options:options completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
if (completedBlock) {
completedBlock(image, error, cacheType);
}
}];
}
- (void)setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state {
[self sd_setBackgroundImageWithURL:url forState:state placeholderImage:nil options:0 completed:nil];
}
- (void)setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder {
[self sd_setBackgroundImageWithURL:url forState:state placeholderImage:placeholder options:0 completed:nil];
}
- (void)setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options {
[self sd_setBackgroundImageWithURL:url forState:state placeholderImage:placeholder options:options completed:nil];
}
- (void)setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state completed:(SDWebImageCompletedBlock)completedBlock {
[self sd_setBackgroundImageWithURL:url forState:state placeholderImage:nil options:0 completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
if (completedBlock) {
completedBlock(image, error, cacheType);
}
}];
}
- (void)setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletedBlock)completedBlock {
[self sd_setBackgroundImageWithURL:url forState:state placeholderImage:placeholder options:0 completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
if (completedBlock) {
completedBlock(image, error, cacheType);
}
}];
}
- (void)setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletedBlock)completedBlock {
[self sd_setBackgroundImageWithURL:url forState:state placeholderImage:placeholder options:options completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
if (completedBlock) {
completedBlock(image, error, cacheType);
}
}];
}
- (void)cancelCurrentImageLoad {
// in a backwards compatible manner, cancel for current state
[self sd_cancelImageLoadForState:self.state];
}
- (void)cancelBackgroundImageLoadForState:(UIControlState)state {
[self sd_cancelBackgroundImageLoadForState:state];
}
@end

View File

@ -1,10 +1,4 @@
// #ifdef SD_GIF
// UIImage+GIF.h
// LBGIFImage
//
// Created by Laurin Brandner on 06.01.12.
// Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
@ -14,6 +8,6 @@
+ (UIImage *)sd_animatedGIFWithData:(NSData *)data; + (UIImage *)sd_animatedGIFWithData:(NSData *)data;
- (UIImage *)sd_animatedImageByScalingAndCroppingToSize:(CGSize)size;
@end @end
#endif

View File

@ -1,161 +1,64 @@
// #ifdef SD_GIF
// UIImage+GIF.m
// LBGIFImage
//
// Created by Laurin Brandner on 06.01.12.
// Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//
#import "UIImage+GIF.h" #import "UIImage+GIF.h"
#import <ImageIO/ImageIO.h> #import <ImageIO/ImageIO.h>
#import "FLAnimatedImage.h"
@implementation UIImage (GIF) @implementation UIImage (GIF)
+ (UIImage *)sd_animatedGIFWithData:(NSData *)data { + (UIImage *)sd_animatedGIFWithData:(NSData *)data {
if (!data) { return [FLAnimatedImage imageWithData:data];
return nil;
}
CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
size_t count = CGImageSourceGetCount(source);
UIImage *animatedImage;
if (count <= 1) {
animatedImage = [[UIImage alloc] initWithData:data];
}
else {
NSMutableArray *images = [NSMutableArray array];
NSTimeInterval duration = 0.0f;
for (size_t i = 0; i < count; i++) {
CGImageRef image = CGImageSourceCreateImageAtIndex(source, i, NULL);
if (!image) {
continue;
}
duration += [self sd_frameDurationAtIndex:i source:source];
[images addObject:[UIImage imageWithCGImage:image scale:[UIScreen mainScreen].scale orientation:UIImageOrientationUp]];
CGImageRelease(image);
}
if (!duration) {
duration = (1.0f / 10.0f) * count;
}
animatedImage = [UIImage animatedImageWithImages:images duration:duration];
}
CFRelease(source);
return animatedImage;
}
+ (float)sd_frameDurationAtIndex:(NSUInteger)index source:(CGImageSourceRef)source {
float frameDuration = 0.1f;
CFDictionaryRef cfFrameProperties = CGImageSourceCopyPropertiesAtIndex(source, index, nil);
NSDictionary *frameProperties = (__bridge NSDictionary *)cfFrameProperties;
NSDictionary *gifProperties = frameProperties[(NSString *)kCGImagePropertyGIFDictionary];
NSNumber *delayTimeUnclampedProp = gifProperties[(NSString *)kCGImagePropertyGIFUnclampedDelayTime];
if (delayTimeUnclampedProp) {
frameDuration = [delayTimeUnclampedProp floatValue];
}
else {
NSNumber *delayTimeProp = gifProperties[(NSString *)kCGImagePropertyGIFDelayTime];
if (delayTimeProp) {
frameDuration = [delayTimeProp floatValue];
}
}
// Many annoying ads specify a 0 duration to make an image flash as quickly as possible.
// We follow Firefox's behavior and use a duration of 100 ms for any frames that specify
// a duration of <= 10 ms. See <rdar://problem/7689300> and <http://webkit.org/b/36082>
// for more information.
if (frameDuration < 0.011f) {
frameDuration = 0.100f;
}
CFRelease(cfFrameProperties);
return frameDuration;
} }
+ (UIImage *)sd_animatedGIFNamed:(NSString *)name { + (UIImage *)sd_animatedGIFNamed:(NSString *)name {
CGFloat scale = [UIScreen mainScreen].scale; CGFloat scale = [UIScreen mainScreen].scale;
if (scale > 1.0f) { //set up possible paths
NSString *retinaPath = [[NSBundle mainBundle] pathForResource:[name stringByAppendingString:@"@2x"] ofType:@"gif"]; NSString *threeTimesResName = [name stringByAppendingString:@"@3x"];
NSString *twoTimesResName = [name stringByAppendingString:@"@2x"];
NSData *data = [NSData dataWithContentsOfFile:retinaPath]; NSString *normalResName = name;
if (data) { NSData *data;
return [UIImage sd_animatedGIFWithData:data]; NSString *path;
}
//get gif for @3x display
NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:@"gif"]; if (scale > 2.0f) {
path = [[NSBundle mainBundle] pathForResource:threeTimesResName ofType:@"gif"];
data = [NSData dataWithContentsOfFile:path]; data = [NSData dataWithContentsOfFile:path];
if (data) {
return [UIImage sd_animatedGIFWithData:data];
}
return [UIImage imageNamed:name];
} }
else {
NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:@"gif"]; //get gif for 2x display or if there is no @3x resource
if (scale > 1.0f && !data) {
NSData *data = [NSData dataWithContentsOfFile:path]; path = [[NSBundle mainBundle] pathForResource:twoTimesResName ofType:@"gif"];
data = [NSData dataWithContentsOfFile:path];
if (data) {
return [UIImage sd_animatedGIFWithData:data];
}
return [UIImage imageNamed:name];
} }
}
//get gif for non-retina display or if there is no @2x or 3x resource
- (UIImage *)sd_animatedImageByScalingAndCroppingToSize:(CGSize)size { if (!data) {
if (CGSizeEqualToSize(self.size, size) || CGSizeEqualToSize(size, CGSizeZero)) { path = [[NSBundle mainBundle] pathForResource:normalResName ofType:@"gif"];
return self; data = [NSData dataWithContentsOfFile:path];
} }
CGSize scaledSize = size; //no data yet? maybe there is only a @2x image
CGPoint thumbnailPoint = CGPointZero; if (!data) {
path = [[NSBundle mainBundle] pathForResource:twoTimesResName ofType:@"gif"];
CGFloat widthFactor = size.width / self.size.width; data = [NSData dataWithContentsOfFile:path];
CGFloat heightFactor = size.height / self.size.height;
CGFloat scaleFactor = (widthFactor > heightFactor) ? widthFactor : heightFactor;
scaledSize.width = self.size.width * scaleFactor;
scaledSize.height = self.size.height * scaleFactor;
if (widthFactor > heightFactor) {
thumbnailPoint.y = (size.height - scaledSize.height) * 0.5;
} }
else if (widthFactor < heightFactor) {
thumbnailPoint.x = (size.width - scaledSize.width) * 0.5; //still no data? could be only a @3x image is provided
if (!data) {
path = [[NSBundle mainBundle] pathForResource:threeTimesResName ofType:@"gif"];
data = [NSData dataWithContentsOfFile:path];
} }
NSMutableArray *scaledImages = [NSMutableArray array]; if (data) {
return [UIImage sd_animatedGIFWithData:data];
for (UIImage *image in self.images) {
UIGraphicsBeginImageContextWithOptions(size, NO, 0.0);
[image drawInRect:CGRectMake(thumbnailPoint.x, thumbnailPoint.y, scaledSize.width, scaledSize.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
[scaledImages addObject:newImage];
UIGraphicsEndImageContext();
} }
return [UIImage animatedImageWithImages:scaledImages duration:self.duration]; //still no resource found --> try to return non-gif image
return [UIImage imageNamed:name];
} }
@end @end
#endif

View File

@ -15,6 +15,10 @@
#import "UIImage+WebP.h" #import "UIImage+WebP.h"
#endif #endif
#ifdef SD_GIF
#import "UIImage+GIF.h"
#endif
@implementation UIImage (MultiFormat) @implementation UIImage (MultiFormat)
+ (UIImage *)sd_imageWithData:(NSData *)data { + (UIImage *)sd_imageWithData:(NSData *)data {
@ -22,18 +26,18 @@
return nil; return nil;
} }
UIImage *image; UIImage *image = nil;
NSString *imageContentType = [NSData sd_contentTypeForImageData:data]; NSString *imageContentType = [NSData sd_contentTypeForImageData:data];
if ([imageContentType isEqualToString:@"image/gif"]) { if ([imageContentType isEqualToString:@"image/gif"]) {
#ifdef SD_GIF
image = [UIImage sd_animatedGIFWithData:data]; image = [UIImage sd_animatedGIFWithData:data];
}
#ifdef SD_WEBP
else if ([imageContentType isEqualToString:@"image/webp"])
{
image = [UIImage sd_imageWithWebPData:data];
}
#endif #endif
else { } else if ([imageContentType isEqualToString:@"image/webp"]) {
#ifdef SD_WEBP
image = [UIImage sd_imageWithWebPData:data];
#endif
} else {
image = [[UIImage alloc] initWithData:data]; image = [[UIImage alloc] initWithData:data];
UIImageOrientation orientation = [self sd_imageOrientationFromImageData:data]; UIImageOrientation orientation = [self sd_imageOrientationFromImageData:data];
if (orientation != UIImageOrientationUp) { if (orientation != UIImageOrientationUp) {

View File

@ -8,12 +8,7 @@
#ifdef SD_WEBP #ifdef SD_WEBP
#import "UIImage+WebP.h" #import "UIImage+WebP.h"
#if !COCOAPODS
#import "webp/decode.h" #import "webp/decode.h"
#else
#import "webp/decode.h"
#endif
// Callback for CGDataProviderRelease // Callback for CGDataProviderRelease
static void FreeImageData(void *info, const void *data, size_t size) static void FreeImageData(void *info, const void *data, size_t size)

View File

@ -43,7 +43,7 @@
* @param completedBlock A block called when operation has been completed. This block has no return value * @param completedBlock A block called when operation has been completed. This block has no return value
* and takes the requested UIImage as first parameter. In case of error the image parameter * and takes the requested UIImage as first parameter. In case of error the image parameter
* is nil and the second parameter may contain an NSError. The third parameter is a Boolean * is nil and the second parameter may contain an NSError. The third parameter is a Boolean
* indicating if the image was retrieved from the local cache or from the network. * indicating if the image was retrived from the local cache or from the network.
* The fourth parameter is the original image url. * The fourth parameter is the original image url.
*/ */
- (void)sd_setHighlightedImageWithURL:(NSURL *)url completed:(SDWebImageCompletionBlock)completedBlock; - (void)sd_setHighlightedImageWithURL:(NSURL *)url completed:(SDWebImageCompletionBlock)completedBlock;
@ -58,7 +58,7 @@
* @param completedBlock A block called when operation has been completed. This block has no return value * @param completedBlock A block called when operation has been completed. This block has no return value
* and takes the requested UIImage as first parameter. In case of error the image parameter * and takes the requested UIImage as first parameter. In case of error the image parameter
* is nil and the second parameter may contain an NSError. The third parameter is a Boolean * is nil and the second parameter may contain an NSError. The third parameter is a Boolean
* indicating if the image was retrieved from the local cache or from the network. * indicating if the image was retrived from the local cache or from the network.
* The fourth parameter is the original image url. * The fourth parameter is the original image url.
*/ */
- (void)sd_setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock; - (void)sd_setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock;
@ -74,7 +74,7 @@
* @param completedBlock A block called when operation has been completed. This block has no return value * @param completedBlock A block called when operation has been completed. This block has no return value
* and takes the requested UIImage as first parameter. In case of error the image parameter * and takes the requested UIImage as first parameter. In case of error the image parameter
* is nil and the second parameter may contain an NSError. The third parameter is a Boolean * is nil and the second parameter may contain an NSError. The third parameter is a Boolean
* indicating if the image was retrieved from the local cache or from the network. * indicating if the image was retrived from the local cache or from the network.
* The fourth parameter is the original image url. * The fourth parameter is the original image url.
*/ */
- (void)sd_setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock; - (void)sd_setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock;
@ -85,16 +85,3 @@
- (void)sd_cancelCurrentHighlightedImageLoad; - (void)sd_cancelCurrentHighlightedImageLoad;
@end @end
@interface UIImageView (HighlightedWebCacheDeprecated)
- (void)setHighlightedImageWithURL:(NSURL *)url __deprecated_msg("Method deprecated. Use `sd_setHighlightedImageWithURL:`");
- (void)setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options __deprecated_msg("Method deprecated. Use `sd_setHighlightedImageWithURL:options:`");
- (void)setHighlightedImageWithURL:(NSURL *)url completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setHighlightedImageWithURL:completed:`");
- (void)setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setHighlightedImageWithURL:options:completed:`");
- (void)setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setHighlightedImageWithURL:options:progress:completed:`");
- (void)cancelCurrentHighlightedImageLoad __deprecated_msg("Use `sd_cancelCurrentHighlightedImageLoad`");
@end

View File

@ -34,17 +34,12 @@
if (url) { if (url) {
__weak __typeof(self)wself = self; __weak __typeof(self)wself = self;
id<SDWebImageOperation> operation = [SDWebImageManager.sharedManager downloadImageWithURL:url options:options progress:progressBlock completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { id<SDWebImageOperation> operation = [SDWebImageManager.sharedManager loadImageWithURL:url options:options progress:progressBlock completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
if (!wself) return; if (!wself) return;
dispatch_main_sync_safe (^ dispatch_main_sync_safe (^
{ {
if (!wself) return; if (!wself) return;
if (image && (options & SDWebImageAvoidAutoSetImage) && completedBlock) if (image) {
{
completedBlock(image, error, cacheType, url);
return;
}
else if (image) {
wself.highlightedImage = image; wself.highlightedImage = image;
[wself setNeedsLayout]; [wself setNeedsLayout];
} }
@ -69,44 +64,3 @@
} }
@end @end
@implementation UIImageView (HighlightedWebCacheDeprecated)
- (void)setHighlightedImageWithURL:(NSURL *)url {
[self sd_setHighlightedImageWithURL:url options:0 progress:nil completed:nil];
}
- (void)setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options {
[self sd_setHighlightedImageWithURL:url options:options progress:nil completed:nil];
}
- (void)setHighlightedImageWithURL:(NSURL *)url completed:(SDWebImageCompletedBlock)completedBlock {
[self sd_setHighlightedImageWithURL:url options:0 progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
if (completedBlock) {
completedBlock(image, error, cacheType);
}
}];
}
- (void)setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options completed:(SDWebImageCompletedBlock)completedBlock {
[self sd_setHighlightedImageWithURL:url options:options progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
if (completedBlock) {
completedBlock(image, error, cacheType);
}
}];
}
- (void)setHighlightedImageWithURL:(NSURL *)url options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletedBlock)completedBlock {
[self sd_setHighlightedImageWithURL:url options:0 progress:progressBlock completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
if (completedBlock) {
completedBlock(image, error, cacheType);
}
}];
}
- (void)cancelCurrentHighlightedImageLoad {
[self sd_cancelCurrentHighlightedImageLoad];
}
@end

View File

@ -92,7 +92,7 @@
* @param completedBlock A block called when operation has been completed. This block has no return value * @param completedBlock A block called when operation has been completed. This block has no return value
* and takes the requested UIImage as first parameter. In case of error the image parameter * and takes the requested UIImage as first parameter. In case of error the image parameter
* is nil and the second parameter may contain an NSError. The third parameter is a Boolean * is nil and the second parameter may contain an NSError. The third parameter is a Boolean
* indicating if the image was retrieved from the local cache or from the network. * indicating if the image was retrived from the local cache or from the network.
* The fourth parameter is the original image url. * The fourth parameter is the original image url.
*/ */
- (void)sd_setImageWithURL:(NSURL *)url completed:(SDWebImageCompletionBlock)completedBlock; - (void)sd_setImageWithURL:(NSURL *)url completed:(SDWebImageCompletionBlock)completedBlock;
@ -107,7 +107,7 @@
* @param completedBlock A block called when operation has been completed. This block has no return value * @param completedBlock A block called when operation has been completed. This block has no return value
* and takes the requested UIImage as first parameter. In case of error the image parameter * and takes the requested UIImage as first parameter. In case of error the image parameter
* is nil and the second parameter may contain an NSError. The third parameter is a Boolean * is nil and the second parameter may contain an NSError. The third parameter is a Boolean
* indicating if the image was retrieved from the local cache or from the network. * indicating if the image was retrived from the local cache or from the network.
* The fourth parameter is the original image url. * The fourth parameter is the original image url.
*/ */
- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletionBlock)completedBlock; - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletionBlock)completedBlock;
@ -123,7 +123,7 @@
* @param completedBlock A block called when operation has been completed. This block has no return value * @param completedBlock A block called when operation has been completed. This block has no return value
* and takes the requested UIImage as first parameter. In case of error the image parameter * and takes the requested UIImage as first parameter. In case of error the image parameter
* is nil and the second parameter may contain an NSError. The third parameter is a Boolean * is nil and the second parameter may contain an NSError. The third parameter is a Boolean
* indicating if the image was retrieved from the local cache or from the network. * indicating if the image was retrived from the local cache or from the network.
* The fourth parameter is the original image url. * The fourth parameter is the original image url.
*/ */
- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock; - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock;
@ -140,13 +140,13 @@
* @param completedBlock A block called when operation has been completed. This block has no return value * @param completedBlock A block called when operation has been completed. This block has no return value
* and takes the requested UIImage as first parameter. In case of error the image parameter * and takes the requested UIImage as first parameter. In case of error the image parameter
* is nil and the second parameter may contain an NSError. The third parameter is a Boolean * is nil and the second parameter may contain an NSError. The third parameter is a Boolean
* indicating if the image was retrieved from the local cache or from the network. * indicating if the image was retrived from the local cache or from the network.
* The fourth parameter is the original image url. * The fourth parameter is the original image url.
*/ */
- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock; - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock;
/** /**
* Set the imageView `image` with an `url` and optionally a placeholder image. * Set the imageView `image` with an `url` and a optionaly placeholder image.
* *
* The download is asynchronous and cached. * The download is asynchronous and cached.
* *
@ -157,10 +157,10 @@
* @param completedBlock A block called when operation has been completed. This block has no return value * @param completedBlock A block called when operation has been completed. This block has no return value
* and takes the requested UIImage as first parameter. In case of error the image parameter * and takes the requested UIImage as first parameter. In case of error the image parameter
* is nil and the second parameter may contain an NSError. The third parameter is a Boolean * is nil and the second parameter may contain an NSError. The third parameter is a Boolean
* indicating if the image was retrieved from the local cache or from the network. * indicating if the image was retrived from the local cache or from the network.
* The fourth parameter is the original image url. * The fourth parameter is the original image url.
*/ */
- (void)sd_setImageWithPreviousCachedImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock; - (void)sd_setImageWithPreviousCachedImageWithURL:(NSURL *)url andPlaceholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock;
/** /**
* Download an array of images and starts them in an animation loop * Download an array of images and starts them in an animation loop
@ -176,40 +176,4 @@
- (void)sd_cancelCurrentAnimationImagesLoad; - (void)sd_cancelCurrentAnimationImagesLoad;
/**
* Show activity UIActivityIndicatorView
*/
- (void)setShowActivityIndicatorView:(BOOL)show;
/**
* set desired UIActivityIndicatorViewStyle
*
* @param style The style of the UIActivityIndicatorView
*/
- (void)setIndicatorStyle:(UIActivityIndicatorViewStyle)style;
@end
@interface UIImageView (WebCacheDeprecated)
- (NSURL *)imageURL __deprecated_msg("Use `sd_imageURL`");
- (void)setImageWithURL:(NSURL *)url __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:`");
- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:placeholderImage:`");
- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:placeholderImage:options`");
- (void)setImageWithURL:(NSURL *)url completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:completed:`");
- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:placeholderImage:completed:`");
- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:placeholderImage:options:completed:`");
- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletedBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setImageWithURL:placeholderImage:options:progress:completed:`");
- (void)sd_setImageWithPreviousCachedImageWithURL:(NSURL *)url andPlaceholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock __deprecated_msg("Method deprecated. Use `sd_setImageWithPreviousCachedImageWithURL:placeholderImage:options:progress:completed:`");
- (void)setAnimationImagesWithURLs:(NSArray *)arrayOfURLs __deprecated_msg("Use `sd_setAnimationImagesWithURLs:`");
- (void)cancelCurrentArrayLoad __deprecated_msg("Use `sd_cancelCurrentAnimationImagesLoad`");
- (void)cancelCurrentImageLoad __deprecated_msg("Use `sd_cancelCurrentImageLoad`");
@end @end

View File

@ -11,9 +11,6 @@
#import "UIView+WebCacheOperation.h" #import "UIView+WebCacheOperation.h"
static char imageURLKey; static char imageURLKey;
static char TAG_ACTIVITY_INDICATOR;
static char TAG_ACTIVITY_STYLE;
static char TAG_ACTIVITY_SHOW;
@implementation UIImageView (WebCache) @implementation UIImageView (WebCache)
@ -52,15 +49,8 @@ static char TAG_ACTIVITY_SHOW;
} }
if (url) { if (url) {
// check if activityView is enabled or not
if ([self showActivityIndicatorView]) {
[self addActivityIndicator];
}
__weak __typeof(self)wself = self; __weak __typeof(self)wself = self;
id <SDWebImageOperation> operation = [SDWebImageManager.sharedManager downloadImageWithURL:url options:options progress:progressBlock completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { id <SDWebImageOperation> operation = [SDWebImageManager.sharedManager loadImageWithURL:url options:options progress:progressBlock completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
[wself removeActivityIndicator];
if (!wself) return; if (!wself) return;
dispatch_main_sync_safe(^{ dispatch_main_sync_safe(^{
if (!wself) return; if (!wself) return;
@ -86,16 +76,15 @@ static char TAG_ACTIVITY_SHOW;
[self sd_setImageLoadOperation:operation forKey:@"UIImageViewImageLoad"]; [self sd_setImageLoadOperation:operation forKey:@"UIImageViewImageLoad"];
} else { } else {
dispatch_main_async_safe(^{ dispatch_main_async_safe(^{
[self removeActivityIndicator]; NSError *error = [NSError errorWithDomain:SDWebImageErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey : @"Trying to load a nil url"}];
if (completedBlock) { if (completedBlock) {
NSError *error = [NSError errorWithDomain:SDWebImageErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey : @"Trying to load a nil url"}];
completedBlock(nil, error, SDImageCacheTypeNone, url); completedBlock(nil, error, SDImageCacheTypeNone, url);
} }
}); });
} }
} }
- (void)sd_setImageWithPreviousCachedImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock { - (void)sd_setImageWithPreviousCachedImageWithURL:(NSURL *)url andPlaceholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock {
NSString *key = [[SDWebImageManager sharedManager] cacheKeyForURL:url]; NSString *key = [[SDWebImageManager sharedManager] cacheKeyForURL:url];
UIImage *lastPreviousCachedImage = [[SDImageCache sharedImageCache] imageFromDiskCacheForKey:key]; UIImage *lastPreviousCachedImage = [[SDImageCache sharedImageCache] imageFromDiskCacheForKey:key];
@ -113,7 +102,7 @@ static char TAG_ACTIVITY_SHOW;
NSMutableArray *operationsArray = [[NSMutableArray alloc] init]; NSMutableArray *operationsArray = [[NSMutableArray alloc] init];
for (NSURL *logoImageURL in arrayOfURLs) { for (NSURL *logoImageURL in arrayOfURLs) {
id <SDWebImageOperation> operation = [SDWebImageManager.sharedManager downloadImageWithURL:logoImageURL options:0 progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { id <SDWebImageOperation> operation = [SDWebImageManager.sharedManager loadImageWithURL:logoImageURL options:0 progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
if (!wself) return; if (!wself) return;
dispatch_main_sync_safe(^{ dispatch_main_sync_safe(^{
__strong UIImageView *sself = wself; __strong UIImageView *sself = wself;
@ -145,137 +134,4 @@ static char TAG_ACTIVITY_SHOW;
[self sd_cancelImageLoadOperationWithKey:@"UIImageViewAnimationImages"]; [self sd_cancelImageLoadOperationWithKey:@"UIImageViewAnimationImages"];
} }
#pragma mark -
- (UIActivityIndicatorView *)activityIndicator {
return (UIActivityIndicatorView *)objc_getAssociatedObject(self, &TAG_ACTIVITY_INDICATOR);
}
- (void)setActivityIndicator:(UIActivityIndicatorView *)activityIndicator {
objc_setAssociatedObject(self, &TAG_ACTIVITY_INDICATOR, activityIndicator, OBJC_ASSOCIATION_RETAIN);
}
- (void)setShowActivityIndicatorView:(BOOL)show{
objc_setAssociatedObject(self, &TAG_ACTIVITY_SHOW, [NSNumber numberWithBool:show], OBJC_ASSOCIATION_RETAIN);
}
- (BOOL)showActivityIndicatorView{
return [objc_getAssociatedObject(self, &TAG_ACTIVITY_SHOW) boolValue];
}
- (void)setIndicatorStyle:(UIActivityIndicatorViewStyle)style{
objc_setAssociatedObject(self, &TAG_ACTIVITY_STYLE, [NSNumber numberWithInt:style], OBJC_ASSOCIATION_RETAIN);
}
- (int)getIndicatorStyle{
return [objc_getAssociatedObject(self, &TAG_ACTIVITY_STYLE) intValue];
}
- (void)addActivityIndicator {
if (!self.activityIndicator) {
self.activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:[self getIndicatorStyle]];
self.activityIndicator.translatesAutoresizingMaskIntoConstraints = NO;
dispatch_main_async_safe(^{
[self addSubview:self.activityIndicator];
[self addConstraint:[NSLayoutConstraint constraintWithItem:self.activityIndicator
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeCenterX
multiplier:1.0
constant:0.0]];
[self addConstraint:[NSLayoutConstraint constraintWithItem:self.activityIndicator
attribute:NSLayoutAttributeCenterY
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeCenterY
multiplier:1.0
constant:0.0]];
});
}
dispatch_main_async_safe(^{
[self.activityIndicator startAnimating];
});
}
- (void)removeActivityIndicator {
if (self.activityIndicator) {
[self.activityIndicator removeFromSuperview];
self.activityIndicator = nil;
}
}
@end
@implementation UIImageView (WebCacheDeprecated)
- (NSURL *)imageURL {
return [self sd_imageURL];
}
- (void)setImageWithURL:(NSURL *)url {
[self sd_setImageWithURL:url placeholderImage:nil options:0 progress:nil completed:nil];
}
- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder {
[self sd_setImageWithURL:url placeholderImage:placeholder options:0 progress:nil completed:nil];
}
- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options {
[self sd_setImageWithURL:url placeholderImage:placeholder options:options progress:nil completed:nil];
}
- (void)setImageWithURL:(NSURL *)url completed:(SDWebImageCompletedBlock)completedBlock {
[self sd_setImageWithURL:url placeholderImage:nil options:0 progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
if (completedBlock) {
completedBlock(image, error, cacheType);
}
}];
}
- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletedBlock)completedBlock {
[self sd_setImageWithURL:url placeholderImage:placeholder options:0 progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
if (completedBlock) {
completedBlock(image, error, cacheType);
}
}];
}
- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletedBlock)completedBlock {
[self sd_setImageWithURL:url placeholderImage:placeholder options:options progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
if (completedBlock) {
completedBlock(image, error, cacheType);
}
}];
}
- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletedBlock)completedBlock {
[self sd_setImageWithURL:url placeholderImage:placeholder options:options progress:progressBlock completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
if (completedBlock) {
completedBlock(image, error, cacheType);
}
}];
}
- (void)sd_setImageWithPreviousCachedImageWithURL:(NSURL *)url andPlaceholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock {
[self sd_setImageWithPreviousCachedImageWithURL:url placeholderImage:placeholder options:options progress:progressBlock completed:completedBlock];
}
- (void)cancelCurrentArrayLoad {
[self sd_cancelCurrentAnimationImagesLoad];
}
- (void)cancelCurrentImageLoad {
[self sd_cancelCurrentImageLoad];
}
- (void)setAnimationImagesWithURLs:(NSArray *)arrayOfURLs {
[self sd_setAnimationImagesWithURLs:arrayOfURLs];
}
@end @end

View File

@ -3,9 +3,13 @@ source 'https://github.com/CocoaPods/Specs.git'
xcodeproj 'SDWebImage Tests' xcodeproj 'SDWebImage Tests'
workspace '../SDWebImage' workspace '../SDWebImage'
target 'Tests' do def import_pods
platform :ios, '7.0' pod 'Expecta', '<=0.3.1' # A Matcher Framework for Objective-C/Cocoa
pod 'Expecta', '<=0.3.1'
pod 'SDWebImage', :path => '../' pod 'SDWebImage', :path => '../'
end
target :ios do
platform :ios, '5.0'
link_with 'Tests'
import_pods
end end

View File

@ -7,8 +7,7 @@
objects = { objects = {
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
2278D185E97AF851CF3F9A07 /* libPods-Tests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F0EF05B6C461610578D6C2A6 /* libPods-Tests.a */; }; ABC8501F672447AA91C788DA /* libPods-ios.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EB0D107E6B4C4094BA2FEE29 /* libPods-ios.a */; };
5F7F38AD1AE2A77A00B0E330 /* TestImage.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 5F7F38AC1AE2A77A00B0E330 /* TestImage.jpg */; };
DA248D57195472AA00390AB0 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA248D56195472AA00390AB0 /* XCTest.framework */; }; DA248D57195472AA00390AB0 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA248D56195472AA00390AB0 /* XCTest.framework */; };
DA248D59195472AA00390AB0 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA248D58195472AA00390AB0 /* Foundation.framework */; }; DA248D59195472AA00390AB0 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA248D58195472AA00390AB0 /* Foundation.framework */; };
DA248D5B195472AA00390AB0 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA248D5A195472AA00390AB0 /* UIKit.framework */; }; DA248D5B195472AA00390AB0 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA248D5A195472AA00390AB0 /* UIKit.framework */; };
@ -19,9 +18,8 @@
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
0EAE9F732E05E3878DC9D2D1 /* Pods-Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Tests/Pods-Tests.debug.xcconfig"; sourceTree = "<group>"; }; 1A6DF883515E8008203AB352 /* Pods-ios.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ios.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ios/Pods-ios.debug.xcconfig"; sourceTree = "<group>"; };
2FAA0419497C5AA7F0EA0E20 /* Pods-Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-Tests/Pods-Tests.release.xcconfig"; sourceTree = "<group>"; }; CA88E6BDE3581B2BFE933C10 /* Pods-ios.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ios.release.xcconfig"; path = "Pods/Target Support Files/Pods-ios/Pods-ios.release.xcconfig"; sourceTree = "<group>"; };
5F7F38AC1AE2A77A00B0E330 /* TestImage.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = TestImage.jpg; sourceTree = "<group>"; };
DA248D53195472AA00390AB0 /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; DA248D53195472AA00390AB0 /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
DA248D56195472AA00390AB0 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; DA248D56195472AA00390AB0 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
DA248D58195472AA00390AB0 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; DA248D58195472AA00390AB0 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; };
@ -32,7 +30,7 @@
DA248D68195475D800390AB0 /* SDImageCacheTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDImageCacheTests.m; sourceTree = "<group>"; }; DA248D68195475D800390AB0 /* SDImageCacheTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDImageCacheTests.m; sourceTree = "<group>"; };
DA248D6A195476AC00390AB0 /* SDWebImageManagerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDWebImageManagerTests.m; sourceTree = "<group>"; }; DA248D6A195476AC00390AB0 /* SDWebImageManagerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDWebImageManagerTests.m; sourceTree = "<group>"; };
DA91BEBB19795BC9006F2536 /* UIImageMultiFormatTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIImageMultiFormatTests.m; sourceTree = "<group>"; }; DA91BEBB19795BC9006F2536 /* UIImageMultiFormatTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIImageMultiFormatTests.m; sourceTree = "<group>"; };
F0EF05B6C461610578D6C2A6 /* libPods-Tests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Tests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; EB0D107E6B4C4094BA2FEE29 /* libPods-ios.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-ios.a"; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
@ -43,7 +41,7 @@
DA248D57195472AA00390AB0 /* XCTest.framework in Frameworks */, DA248D57195472AA00390AB0 /* XCTest.framework in Frameworks */,
DA248D5B195472AA00390AB0 /* UIKit.framework in Frameworks */, DA248D5B195472AA00390AB0 /* UIKit.framework in Frameworks */,
DA248D59195472AA00390AB0 /* Foundation.framework in Frameworks */, DA248D59195472AA00390AB0 /* Foundation.framework in Frameworks */,
2278D185E97AF851CF3F9A07 /* libPods-Tests.a in Frameworks */, ABC8501F672447AA91C788DA /* libPods-ios.a in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -53,8 +51,8 @@
8D1A343B1A6D91E95D7795EF /* Pods */ = { 8D1A343B1A6D91E95D7795EF /* Pods */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
0EAE9F732E05E3878DC9D2D1 /* Pods-Tests.debug.xcconfig */, 1A6DF883515E8008203AB352 /* Pods-ios.debug.xcconfig */,
2FAA0419497C5AA7F0EA0E20 /* Pods-Tests.release.xcconfig */, CA88E6BDE3581B2BFE933C10 /* Pods-ios.release.xcconfig */,
); );
name = Pods; name = Pods;
sourceTree = "<group>"; sourceTree = "<group>";
@ -83,7 +81,7 @@
DA248D56195472AA00390AB0 /* XCTest.framework */, DA248D56195472AA00390AB0 /* XCTest.framework */,
DA248D58195472AA00390AB0 /* Foundation.framework */, DA248D58195472AA00390AB0 /* Foundation.framework */,
DA248D5A195472AA00390AB0 /* UIKit.framework */, DA248D5A195472AA00390AB0 /* UIKit.framework */,
F0EF05B6C461610578D6C2A6 /* libPods-Tests.a */, EB0D107E6B4C4094BA2FEE29 /* libPods-ios.a */,
); );
name = Frameworks; name = Frameworks;
sourceTree = "<group>"; sourceTree = "<group>";
@ -91,7 +89,6 @@
DA248D5C195472AA00390AB0 /* Tests */ = { DA248D5C195472AA00390AB0 /* Tests */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
5F7F38AC1AE2A77A00B0E330 /* TestImage.jpg */,
DA248D5D195472AA00390AB0 /* Supporting Files */, DA248D5D195472AA00390AB0 /* Supporting Files */,
DA248D68195475D800390AB0 /* SDImageCacheTests.m */, DA248D68195475D800390AB0 /* SDImageCacheTests.m */,
DA248D6A195476AC00390AB0 /* SDWebImageManagerTests.m */, DA248D6A195476AC00390AB0 /* SDWebImageManagerTests.m */,
@ -117,12 +114,11 @@
isa = PBXNativeTarget; isa = PBXNativeTarget;
buildConfigurationList = DA248D67195472AA00390AB0 /* Build configuration list for PBXNativeTarget "Tests" */; buildConfigurationList = DA248D67195472AA00390AB0 /* Build configuration list for PBXNativeTarget "Tests" */;
buildPhases = ( buildPhases = (
FBC8982311CD4ED9A3006D45 /* 📦 Check Pods Manifest.lock */, FBC8982311CD4ED9A3006D45 /* Check Pods Manifest.lock */,
DA248D4F195472AA00390AB0 /* Sources */, DA248D4F195472AA00390AB0 /* Sources */,
DA248D50195472AA00390AB0 /* Frameworks */, DA248D50195472AA00390AB0 /* Frameworks */,
DA248D51195472AA00390AB0 /* Resources */, DA248D51195472AA00390AB0 /* Resources */,
D6347736BDF64FC5A4D078A4 /* 📦 Copy Pods Resources */, D6347736BDF64FC5A4D078A4 /* Copy Pods Resources */,
4B51E412BA3594400947AC71 /* 📦 Embed Pods Frameworks */,
); );
buildRules = ( buildRules = (
); );
@ -163,7 +159,6 @@
isa = PBXResourcesBuildPhase; isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
5F7F38AD1AE2A77A00B0E330 /* TestImage.jpg in Resources */,
DA248D61195472AA00390AB0 /* InfoPlist.strings in Resources */, DA248D61195472AA00390AB0 /* InfoPlist.strings in Resources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
@ -171,44 +166,29 @@
/* End PBXResourcesBuildPhase section */ /* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */
4B51E412BA3594400947AC71 /* 📦 Embed Pods Frameworks */ = { D6347736BDF64FC5A4D078A4 /* Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
); );
inputPaths = ( inputPaths = (
); );
name = "📦 Embed Pods Frameworks"; name = "Copy Pods Resources";
outputPaths = ( outputPaths = (
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh; shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Tests/Pods-Tests-frameworks.sh\"\n"; shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-ios/Pods-ios-resources.sh\"\n";
showEnvVarsInLog = 0; showEnvVarsInLog = 0;
}; };
D6347736BDF64FC5A4D078A4 /* 📦 Copy Pods Resources */ = { FBC8982311CD4ED9A3006D45 /* Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
); );
inputPaths = ( inputPaths = (
); );
name = "📦 Copy Pods Resources"; name = "Check Pods Manifest.lock";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Tests/Pods-Tests-resources.sh\"\n";
showEnvVarsInLog = 0;
};
FBC8982311CD4ED9A3006D45 /* 📦 Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "📦 Check Pods Manifest.lock";
outputPaths = ( outputPaths = (
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
@ -257,7 +237,7 @@
}; };
DA248D65195472AA00390AB0 /* Debug */ = { DA248D65195472AA00390AB0 /* Debug */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
baseConfigurationReference = 0EAE9F732E05E3878DC9D2D1 /* Pods-Tests.debug.xcconfig */; baseConfigurationReference = 1A6DF883515E8008203AB352 /* Pods-ios.debug.xcconfig */;
buildSettings = { buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO; ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
@ -274,6 +254,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
FRAMEWORK_SEARCH_PATHS = ( FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)", "$(inherited)",
"$(DEVELOPER_FRAMEWORKS_DIR)", "$(DEVELOPER_FRAMEWORKS_DIR)",
); );
@ -304,7 +285,7 @@
}; };
DA248D66195472AA00390AB0 /* Release */ = { DA248D66195472AA00390AB0 /* Release */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
baseConfigurationReference = 2FAA0419497C5AA7F0EA0E20 /* Pods-Tests.release.xcconfig */; baseConfigurationReference = CA88E6BDE3581B2BFE933C10 /* Pods-ios.release.xcconfig */;
buildSettings = { buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO; ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
@ -322,6 +303,7 @@
COPY_PHASE_STRIP = YES; COPY_PHASE_STRIP = YES;
ENABLE_NS_ASSERTIONS = NO; ENABLE_NS_ASSERTIONS = NO;
FRAMEWORK_SEARCH_PATHS = ( FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)", "$(inherited)",
"$(DEVELOPER_FRAMEWORKS_DIR)", "$(DEVELOPER_FRAMEWORKS_DIR)",
); );

View File

@ -14,10 +14,9 @@
#import "SDImageCache.h" #import "SDImageCache.h"
NSString *kImageTestKey = @"TestImageKey.jpg";
@interface SDImageCacheTests : XCTestCase @interface SDImageCacheTests : XCTestCase
@property (strong, nonatomic) SDImageCache *sharedImageCache;
@end @end
@implementation SDImageCacheTests @implementation SDImageCacheTests
@ -26,8 +25,6 @@ NSString *kImageTestKey = @"TestImageKey.jpg";
{ {
[super setUp]; [super setUp];
// Put setup code here. This method is called before the invocation of each test method in the class. // Put setup code here. This method is called before the invocation of each test method in the class.
self.sharedImageCache = [SDImageCache sharedImageCache];
[self clearAllCaches];
} }
- (void)tearDown - (void)tearDown
@ -37,189 +34,9 @@ NSString *kImageTestKey = @"TestImageKey.jpg";
} }
- (void)testSharedImageCache { - (void)testSharedImageCache {
expect(self.sharedImageCache).toNot.beNil(); SDImageCache *sharedImageCache = [SDImageCache sharedImageCache];
}
- (void)testSingleton{
expect(self.sharedImageCache).to.equal([SDImageCache sharedImageCache]);
}
- (void)testClearDiskCache{
[self.sharedImageCache storeImage:[self imageForTesting] forKey:kImageTestKey];
[self.sharedImageCache clearDiskOnCompletion:^{
expect([self.sharedImageCache diskImageExistsWithKey:kImageTestKey]).to.equal(NO);
expect([self.sharedImageCache imageFromMemoryCacheForKey:kImageTestKey]).to.equal([self imageForTesting]);
}];
}
- (void)testClearMemoryCache{
[self.sharedImageCache storeImage:[self imageForTesting] forKey:kImageTestKey];
[self.sharedImageCache clearMemory];
expect([self.sharedImageCache imageFromMemoryCacheForKey:kImageTestKey]).to.beNil;
// Seems not able to access the files correctly (maybe only from test?)
//expect([self.sharedImageCache diskImageExistsWithKey:kImageTestKey]).to.equal(YES);
[self.sharedImageCache diskImageExistsWithKey:kImageTestKey completion:^(BOOL isInCache) {
expect(isInCache).to.equal(YES);
}];
}
// Testing storeImage:forKey:
- (void)testInsertionOfImage {
UIImage *image = [self imageForTesting];
[self.sharedImageCache storeImage:image forKey:kImageTestKey];
expect([self.sharedImageCache imageFromMemoryCacheForKey:kImageTestKey]).to.equal(image);
expect([self.sharedImageCache imageFromDiskCacheForKey:kImageTestKey]).to.equal(image);
}
// Testing storeImage:forKey:toDisk:YES
- (void)testInsertionOfImageForcingDiskStorage{
UIImage *image = [self imageForTesting];
[self.sharedImageCache storeImage:image forKey:kImageTestKey toDisk:YES];
expect([self.sharedImageCache imageFromMemoryCacheForKey:kImageTestKey]).to.equal(image);
// Seems not able to access the files correctly (maybe only from test?)
//expect([self.sharedImageCache diskImageExistsWithKey:kImageTestKey]).to.equal(YES);
[self.sharedImageCache diskImageExistsWithKey:kImageTestKey completion:^(BOOL isInCache) {
expect(isInCache).to.equal(YES);
}];
}
// Testing storeImage:forKey:toDisk:NO
- (void)testInsertionOfImageOnlyInMemory {
UIImage *image = [self imageForTesting];
[self.sharedImageCache storeImage:image forKey:@"TestImage" toDisk:NO];
[self.sharedImageCache diskImageExistsWithKey:@"TestImage" completion:^(BOOL isInCache) {
expect(isInCache).to.equal(YES);
}];
[self.sharedImageCache clearMemory];
[self.sharedImageCache diskImageExistsWithKey:@"TestImage" completion:^(BOOL isInCache) {
expect(isInCache).to.equal(NO);
}];
}
- (void)testRetrievalImageThroughNSOperation{
//- (NSOperation *)queryDiskCacheForKey:(NSString *)key done:(SDWebImageQueryCompletedBlock)doneBlock;
UIImage *imageForTesting = [self imageForTesting];
[self.sharedImageCache storeImage:imageForTesting forKey:kImageTestKey];
NSOperation *operation = [self.sharedImageCache queryDiskCacheForKey:kImageTestKey done:^(UIImage *image, SDImageCacheType cacheType) {
expect(image).to.equal(imageForTesting);
}];
expect(operation).toNot.beNil;
}
- (void)testRemoveImageForKey{
[self.sharedImageCache storeImage:[self imageForTesting] forKey:kImageTestKey];
[self.sharedImageCache removeImageForKey:kImageTestKey];
expect([self.sharedImageCache imageFromMemoryCacheForKey:kImageTestKey]).to.beNil;
expect([self.sharedImageCache imageFromDiskCacheForKey:kImageTestKey]).to.beNil;
}
- (void)testRemoveImageForKeyWithCompletion{
[self.sharedImageCache storeImage:[self imageForTesting] forKey:kImageTestKey];
[self.sharedImageCache removeImageForKey:kImageTestKey withCompletion:^{
expect([self.sharedImageCache imageFromDiskCacheForKey:kImageTestKey]).to.beNil;
expect([self.sharedImageCache imageFromMemoryCacheForKey:kImageTestKey]).to.beNil;
}];
}
- (void)testRemoveImageForKeyNotFromDisk{
[self.sharedImageCache storeImage:[self imageForTesting] forKey:kImageTestKey];
[self.sharedImageCache removeImageForKey:kImageTestKey fromDisk:NO];
expect([self.sharedImageCache imageFromDiskCacheForKey:kImageTestKey]).toNot.beNil;
expect([self.sharedImageCache imageFromMemoryCacheForKey:kImageTestKey]).to.beNil;
}
- (void)testRemoveImageForKeyFromDisk{
[self.sharedImageCache storeImage:[self imageForTesting] forKey:kImageTestKey];
[self.sharedImageCache removeImageForKey:kImageTestKey fromDisk:NO];
expect([self.sharedImageCache imageFromDiskCacheForKey:kImageTestKey]).to.beNil;
expect([self.sharedImageCache imageFromMemoryCacheForKey:kImageTestKey]).to.beNil;
}
- (void)testRemoveImageforKeyNotFromDiskWithCompletion{
[self.sharedImageCache storeImage:[self imageForTesting] forKey:kImageTestKey];
[self.sharedImageCache removeImageForKey:kImageTestKey fromDisk:NO withCompletion:^{
expect([self.sharedImageCache imageFromDiskCacheForKey:kImageTestKey]).toNot.beNil;
expect([self.sharedImageCache imageFromMemoryCacheForKey:kImageTestKey]).to.beNil;
}];
}
- (void)testRemoveImageforKeyFromDiskWithCompletion{
[self.sharedImageCache storeImage:[self imageForTesting] forKey:kImageTestKey];
[self.sharedImageCache removeImageForKey:kImageTestKey fromDisk:YES withCompletion:^{
expect([self.sharedImageCache imageFromDiskCacheForKey:kImageTestKey]).to.beNil;
expect([self.sharedImageCache imageFromMemoryCacheForKey:kImageTestKey]).to.beNil;
}];
}
// TODO -- Testing insertion with recalculate
- (void)testInsertionOfImageOnlyInDisk {
}
- (void)testInitialCacheSize{
expect([self.sharedImageCache getSize]).to.equal(0);
}
- (void)testInitialDiskCount{
[self.sharedImageCache storeImage:[self imageForTesting] forKey:kImageTestKey];
expect([self.sharedImageCache getDiskCount]).to.equal(1);
}
- (void)testDiskCountAfterInsertion{
[self.sharedImageCache storeImage:[self imageForTesting] forKey:kImageTestKey];
expect([self.sharedImageCache getDiskCount]).to.equal(1);
}
- (void)testDefaultCachePathForAnyKey{
NSString *path = [self.sharedImageCache defaultCachePathForKey:kImageTestKey];
expect(path).toNot.beNil;
}
- (void)testCachePathForNonExistingKey{
NSString *path = [self.sharedImageCache cachePathForKey:kImageTestKey inPath:[self.sharedImageCache defaultCachePathForKey:kImageTestKey]];
expect(path).to.beNil;
}
- (void)testCachePathForExistingKey{
[self.sharedImageCache storeImage:[self imageForTesting] forKey:kImageTestKey];
NSString *path = [self.sharedImageCache cachePathForKey:kImageTestKey inPath:[self.sharedImageCache defaultCachePathForKey:kImageTestKey]];
expect(path).notTo.beNil;
}
// TODO -- Testing image data insertion
- (void)testInsertionOfImageData {
NSData *imageData = [NSData dataWithContentsOfFile:[self testImagePath]]; expect(sharedImageCache).toNot.beNil();
[self.sharedImageCache storeImageDataToDisk:imageData forKey:kImageTestKey];
UIImage *storedImageFromMemory = [self.sharedImageCache imageFromMemoryCacheForKey:kImageTestKey];
expect(storedImageFromMemory).to.equal(nil);
NSString *cachePath = [self.sharedImageCache defaultCachePathForKey:kImageTestKey];
NSData *storedImageData = [NSData dataWithContentsOfFile:cachePath];
expect([storedImageData isEqualToData:imageData]).will.beTruthy;
[self.sharedImageCache diskImageExistsWithKey:kImageTestKey completion:^(BOOL isInCache) {
expect(isInCache).to.equal(YES);
}];
}
#pragma mark Helper methods
- (void)clearAllCaches{
[self.sharedImageCache clearDisk];
[self.sharedImageCache clearMemory];
}
- (UIImage *)imageForTesting{
return [UIImage imageWithContentsOfFile:[self testImagePath]];
}
- (NSString *)testImagePath {
NSBundle *testBundle = [NSBundle bundleForClass:[self class]];
return [testBundle pathForResource:@"TestImage" ofType:@"jpg"];
} }
@end @end

View File

@ -38,9 +38,9 @@ static int64_t kAsyncTestTimeout = 5;
- (void)testThatDownloadInvokesCompletionBlockWithCorrectParamsAsync { - (void)testThatDownloadInvokesCompletionBlockWithCorrectParamsAsync {
__block XCTestExpectation *expectation = [self expectationWithDescription:@"Image download completes"]; __block XCTestExpectation *expectation = [self expectationWithDescription:@"Image download completes"];
NSURL *originalImageURL = [NSURL URLWithString:@"http://s3.amazonaws.com/fast-image-cache/demo-images/FICDDemoImage000.jpg"]; NSURL *originalImageURL = [NSURL URLWithString:@"https://www.google.gr/images/srpr/logo11w.png"];
[[SDWebImageManager sharedManager] downloadImageWithURL:originalImageURL options:SDWebImageRefreshCached progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { [[SDWebImageManager sharedManager] loadImageWithURL:originalImageURL options:SDWebImageRefreshCached progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
expect(image).toNot.beNil(); expect(image).toNot.beNil();
expect(error).to.beNil(); expect(error).to.beNil();
expect(originalImageURL).to.equal(imageURL); expect(originalImageURL).to.equal(imageURL);
@ -57,7 +57,7 @@ static int64_t kAsyncTestTimeout = 5;
NSURL *originalImageURL = [NSURL URLWithString:@"http://static2.dmcdn.net/static/video/656/177/44771656:jpeg_preview_small.png"]; NSURL *originalImageURL = [NSURL URLWithString:@"http://static2.dmcdn.net/static/video/656/177/44771656:jpeg_preview_small.png"];
[[SDWebImageManager sharedManager] downloadImageWithURL:originalImageURL options:SDWebImageRefreshCached progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { [[SDWebImageManager sharedManager] loadImageWithURL:originalImageURL options:SDWebImageRefreshCached progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
expect(image).to.beNil(); expect(image).to.beNil();
expect(error).toNot.beNil(); expect(error).toNot.beNil();
expect(originalImageURL).to.equal(imageURL); expect(originalImageURL).to.equal(imageURL);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

1
Vendors/AFNetworking Submodule

@ -0,0 +1 @@
Subproject commit f38608bf2f7f5e13e673f3d77cf9b4fa5e4aad97

@ -0,0 +1 @@
Subproject commit b46cc40d00ee630ccdbb85fbdc0f47e9e2785a10

@ -1 +1 @@
Subproject commit 1525784d5bc1d9e7e74ff18f9d21a910b60552af Subproject commit 326b5fb863a43ab8cb225bca913e9025f727f078

View File

@ -7,7 +7,7 @@
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string> <string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <string>com.dailymotion.$(PRODUCT_NAME:rfc1034identifier)</string>
<key>CFBundleInfoDictionaryVersion</key> <key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string> <string>6.0</string>
<key>CFBundleName</key> <key>CFBundleName</key>
@ -15,7 +15,7 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>FMWK</string> <string>FMWK</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>3.8.1</string> <string>1.0</string>
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>????</string> <string>????</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>

View File

@ -28,9 +28,7 @@ FOUNDATION_EXPORT const unsigned char WebImageVersionString[];
#import <WebImage/UIImage+MultiFormat.h> #import <WebImage/UIImage+MultiFormat.h>
#import <WebImage/SDWebImageOperation.h> #import <WebImage/SDWebImageOperation.h>
#import <WebImage/SDWebImageDownloader.h> #import <WebImage/SDWebImageDownloader.h>
#if !TARGET_OS_TV
#import <WebImage/MKAnnotationView+WebCache.h> #import <WebImage/MKAnnotationView+WebCache.h>
#endif
#import <WebImage/SDWebImageDecoder.h> #import <WebImage/SDWebImageDecoder.h>
#import <WebImage/UIImage+WebP.h> #import <WebImage/UIImage+WebP.h>
#import <WebImage/UIImage+GIF.h> #import <WebImage/UIImage+GIF.h>