Merge branch '4.x' into gif

# Conflicts:
#	SDWebImage.xcodeproj/project.pbxproj
This commit is contained in:
Bogdan Poplauschi 2016-06-07 08:39:17 +03:00
commit 7684fbd9a7
38 changed files with 479 additions and 343 deletions

View File

@ -39,4 +39,4 @@ script:
- echo Run the tests - echo Run the tests
- pod install --project-directory=Tests - pod install --project-directory=Tests
- xcodebuild clean -workspace SDWebImage.xcworkspace -scheme 'SDWebImage-static' -sdk iphonesimulator PLATFORM_NAME=iphonesimulator -configuration Debug | xcpretty -c - xcodebuild clean -workspace SDWebImage.xcworkspace -scheme 'SDWebImage-static' -sdk iphonesimulator PLATFORM_NAME=iphonesimulator -configuration Debug | xcpretty -c
- xcodebuild test -workspace SDWebImage.xcworkspace -scheme 'Tests' -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 6,OS=latest' -configuration Debug | xcpretty -c - xcodebuild test -workspace SDWebImage.xcworkspace -scheme 'Tests' -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 6,OS=latest' -configuration Debug | xcpretty -c

View File

@ -1,3 +1,20 @@
## [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 #1533 #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) ## [3.7.6 Patch release for 3.7.0 on May 8th, 2016](https://github.com/rs/SDWebImage/releases/tag/3.7.6)
#### Infrastructure: #### Infrastructure:

View File

@ -323,7 +323,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 = 6.0; IPHONEOS_DEPLOYMENT_TARGET = 7.0;
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos; SDKROOT = iphoneos;
}; };
@ -341,7 +341,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 = 6.0; IPHONEOS_DEPLOYMENT_TARGET = 7.0;
OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1";
SDKROOT = iphoneos; SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES; VALIDATE_PRODUCT = YES;

View File

@ -1,10 +1,10 @@
// /*
// AppDelegate.h * This file is part of the SDWebImage package.
// SDWebImage Demo * (c) Olivier Poitrey <rs@dailymotion.com>
// *
// Created by Olivier Poitrey on 09/05/12. * For the full copyright and license information, please view the LICENSE
// Copyright (c) 2012 Dailymotion. All rights reserved. * file that was distributed with this source code.
// */
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>

View File

@ -1,10 +1,10 @@
// /*
// AppDelegate.m * This file is part of the SDWebImage package.
// SDWebImage Demo * (c) Olivier Poitrey <rs@dailymotion.com>
// *
// Created by Olivier Poitrey on 09/05/12. * For the full copyright and license information, please view the LICENSE
// Copyright (c) 2012 Dailymotion. All rights reserved. * file that was distributed with this source code.
// */
#import "AppDelegate.h" #import "AppDelegate.h"

View File

@ -1,10 +1,10 @@
// /*
// DetailViewController.h * This file is part of the SDWebImage package.
// SDWebImage Demo * (c) Olivier Poitrey <rs@dailymotion.com>
// *
// Created by Olivier Poitrey on 09/05/12. * For the full copyright and license information, please view the LICENSE
// Copyright (c) 2012 Dailymotion. All rights reserved. * file that was distributed with this source code.
// */
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>

View File

@ -1,10 +1,10 @@
// /*
// DetailViewController.m * This file is part of the SDWebImage package.
// SDWebImage Demo * (c) Olivier Poitrey <rs@dailymotion.com>
// *
// Created by Olivier Poitrey on 09/05/12. * For the full copyright and license information, please view the LICENSE
// Copyright (c) 2012 Dailymotion. All rights reserved. * file that was distributed with this source code.
// */
#import "DetailViewController.h" #import "DetailViewController.h"
#import <SDWebImage/UIImageView+WebCache.h> #import <SDWebImage/UIImageView+WebCache.h>

View File

@ -1,10 +1,10 @@
// /*
// MasterViewController.h * This file is part of the SDWebImage package.
// SDWebImage Demo * (c) Olivier Poitrey <rs@dailymotion.com>
// *
// Created by Olivier Poitrey on 09/05/12. * For the full copyright and license information, please view the LICENSE
// Copyright (c) 2012 Dailymotion. All rights reserved. * file that was distributed with this source code.
// */
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>

View File

@ -1,10 +1,10 @@
// /*
// MasterViewController.m * This file is part of the SDWebImage package.
// SDWebImage Demo * (c) Olivier Poitrey <rs@dailymotion.com>
// *
// Created by Olivier Poitrey on 09/05/12. * For the full copyright and license information, please view the LICENSE
// Copyright (c) 2012 Dailymotion. All rights reserved. * file that was distributed with this source code.
// */
#import "MasterViewController.h" #import "MasterViewController.h"
#import <SDWebImage/UIImageView+WebCache.h> #import <SDWebImage/UIImageView+WebCache.h>

View File

@ -1,10 +1,10 @@
// /*
// main.m * This file is part of the SDWebImage package.
// SDWebImage Demo * (c) Olivier Poitrey <rs@dailymotion.com>
// *
// Created by Olivier Poitrey on 09/05/12. * For the full copyright and license information, please view the LICENSE
// Copyright (c) 2012 Dailymotion. All rights reserved. * file that was distributed with this source code.
// */
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>

View File

@ -120,8 +120,8 @@ There are three ways to use SDWebImage in your project:
#### Podfile #### Podfile
``` ```
platform :ios, '6.1' platform :ios, '7.0'
pod 'SDWebImage', '~>3.7' pod 'SDWebImage', '~>3.8'
``` ```
If you are using Swift, be sure to add `use_frameworks!` and set your target to iOS 8+: If you are using Swift, be sure to add `use_frameworks!` and set your target to iOS 8+:

View File

@ -1,7 +1,7 @@
Pod::Spec.new do |s| Pod::Spec.new do |s|
s.name = 'SDWebImage' s.name = 'SDWebImage'
s.version = '3.7.6' s.version = '3.8.0'
s.ios.deployment_target = '5.0' s.ios.deployment_target = '7.0'
s.tvos.deployment_target = '9.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.'
@ -29,7 +29,7 @@ Pod::Spec.new do |s|
end end
s.subspec 'MapKit' do |mk| s.subspec 'MapKit' do |mk|
mk.ios.deployment_target = '5.0' 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'

View File

@ -1469,7 +1469,7 @@
GCC_WARN_UNUSED_PARAMETER = NO; GCC_WARN_UNUSED_PARAMETER = NO;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = Vendors/libwebp/src; HEADER_SEARCH_PATHS = Vendors/libwebp/src;
IPHONEOS_DEPLOYMENT_TARGET = 6.0; IPHONEOS_DEPLOYMENT_TARGET = 7.0;
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
OTHER_LDFLAGS = "-ObjC"; OTHER_LDFLAGS = "-ObjC";
RUN_CLANG_STATIC_ANALYZER = YES; RUN_CLANG_STATIC_ANALYZER = YES;
@ -1524,7 +1524,7 @@
GCC_WARN_UNUSED_PARAMETER = NO; GCC_WARN_UNUSED_PARAMETER = NO;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = Vendors/libwebp/src; HEADER_SEARCH_PATHS = Vendors/libwebp/src;
IPHONEOS_DEPLOYMENT_TARGET = 6.0; IPHONEOS_DEPLOYMENT_TARGET = 7.0;
OTHER_LDFLAGS = "-ObjC"; OTHER_LDFLAGS = "-ObjC";
RUN_CLANG_STATIC_ANALYZER = YES; RUN_CLANG_STATIC_ANALYZER = YES;
SDKROOT = iphoneos; SDKROOT = iphoneos;

View File

@ -1,10 +1,10 @@
// /*
// MKAnnotationView+WebCache.h * This file is part of the SDWebImage package.
// SDWebImage * (c) Olivier Poitrey <rs@dailymotion.com>
// *
// Created by Olivier Poitrey on 14/03/12. * For the full copyright and license information, please view the LICENSE
// Copyright (c) 2012 Dailymotion. All rights reserved. * file that was distributed with this source code.
// */
#import "MapKit/MapKit.h" #import "MapKit/MapKit.h"
#import "SDWebImageManager.h" #import "SDWebImageManager.h"

View File

@ -1,10 +1,10 @@
// /*
// MKAnnotationView+WebCache.m * This file is part of the SDWebImage package.
// SDWebImage * (c) Olivier Poitrey <rs@dailymotion.com>
// *
// Created by Olivier Poitrey on 14/03/12. * For the full copyright and license information, please view the LICENSE
// Copyright (c) 2012 Dailymotion. All rights reserved. * file that was distributed with this source code.
// */
#import "MKAnnotationView+WebCache.h" #import "MKAnnotationView+WebCache.h"
#import "objc/runtime.h" #import "objc/runtime.h"

View File

@ -1,7 +1,11 @@
// /*
// Created by Fabrice Aneche on 06/01/14. * This file is part of the SDWebImage package.
// Copyright (c) 2014 Dailymotion. All rights reserved. * (c) Olivier Poitrey <rs@dailymotion.com>
// * (c) Fabrice Aneche
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>

View File

@ -1,7 +1,11 @@
// /*
// Created by Fabrice Aneche on 06/01/14. * This file is part of the SDWebImage package.
// Copyright (c) 2014 Dailymotion. All rights reserved. * (c) Olivier Poitrey <rs@dailymotion.com>
// * (c) Fabrice Aneche
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
#import "NSData+ImageContentType.h" #import "NSData+ImageContentType.h"

View File

@ -1,10 +1,10 @@
// /*
// SDWebImageCompat.m * This file is part of the SDWebImage package.
// SDWebImage * (c) Olivier Poitrey <rs@dailymotion.com>
// *
// Created by Olivier Poitrey on 11/12/12. * For the full copyright and license information, please view the LICENSE
// Copyright (c) 2012 Dailymotion. All rights reserved. * file that was distributed with this source code.
// */
#import "SDWebImageCompat.h" #import "SDWebImageCompat.h"

View File

@ -1,8 +1,7 @@
/* /*
* This file is part of the SDWebImage package. * This file is part of the SDWebImage package.
* (c) Olivier Poitrey <rs@dailymotion.com> * (c) Olivier Poitrey <rs@dailymotion.com>
* * (c) james <https://github.com/mystcolor>
* Created by james <https://github.com/mystcolor> on 9/28/11.
* *
* For the full copyright and license information, please view the LICENSE * For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code. * file that was distributed with this source code.

View File

@ -1,8 +1,7 @@
/* /*
* This file is part of the SDWebImage package. * This file is part of the SDWebImage package.
* (c) Olivier Poitrey <rs@dailymotion.com> * (c) Olivier Poitrey <rs@dailymotion.com>
* * (c) james <https://github.com/mystcolor>
* Created by james <https://github.com/mystcolor> on 9/28/11.
* *
* For the full copyright and license information, please view the LICENSE * For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code. * file that was distributed with this source code.

View File

@ -14,7 +14,7 @@
@end @end
@interface SDWebImageDownloader () @interface SDWebImageDownloader () <NSURLSessionTaskDelegate, NSURLSessionDataDelegate>
@property (strong, nonatomic) NSOperationQueue *downloadQueue; @property (strong, nonatomic) NSOperationQueue *downloadQueue;
@property (weak, nonatomic) NSOperation *lastAddedOperation; @property (weak, nonatomic) NSOperation *lastAddedOperation;
@ -24,6 +24,9 @@
// 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
@ -75,11 +78,26 @@
#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);
} }
@ -120,7 +138,8 @@
__weak SDWebImageDownloader *wself = self; __weak SDWebImageDownloader *wself = self;
return [self addProgressCallback:progressBlock completedBlock:completedBlock forURL:url createCallback:^SDWebImageDownloaderOperation *{ return [self addProgressCallback:progressBlock completedBlock:completedBlock forURL:url createCallback:^SDWebImageDownloaderOperation *{
NSTimeInterval timeoutInterval = wself.downloadTimeout; __strong __typeof (wself) sself = wself;
NSTimeInterval timeoutInterval = sself.downloadTimeout;
if (timeoutInterval == 0.0) { if (timeoutInterval == 0.0) {
timeoutInterval = 15.0; timeoutInterval = 15.0;
} }
@ -129,19 +148,19 @@
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url cachePolicy:(options & SDWebImageDownloaderUseNSURLCache ? NSURLRequestUseProtocolCachePolicy : NSURLRequestReloadIgnoringLocalCacheData) timeoutInterval:timeoutInterval]; NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url cachePolicy:(options & SDWebImageDownloaderUseNSURLCache ? NSURLRequestUseProtocolCachePolicy : NSURLRequestReloadIgnoringLocalCacheData) timeoutInterval:timeoutInterval];
request.HTTPShouldHandleCookies = (options & SDWebImageDownloaderHandleCookies); request.HTTPShouldHandleCookies = (options & SDWebImageDownloaderHandleCookies);
request.HTTPShouldUsePipelining = YES; request.HTTPShouldUsePipelining = YES;
if (wself.headersFilter) { if (sself.headersFilter) {
request.allHTTPHeaderFields = wself.headersFilter(url, [wself.HTTPHeaders copy]); request.allHTTPHeaderFields = sself.headersFilter(url, [sself.HTTPHeaders copy]);
} }
else { else {
request.allHTTPHeaderFields = wself.HTTPHeaders; request.allHTTPHeaderFields = sself.HTTPHeaders;
} }
SDWebImageDownloaderOperation *operation = [[wself.operationClass alloc] initWithRequest:request options:options]; SDWebImageDownloaderOperation *operation = [[sself.operationClass alloc] initWithRequest:request inSession:sself.session options:options];
operation.shouldDecompressImages = wself.shouldDecompressImages; operation.shouldDecompressImages = sself.shouldDecompressImages;
if (wself.urlCredential) { if (sself.urlCredential) {
operation.credential = wself.urlCredential; operation.credential = sself.urlCredential;
} else if (wself.username && wself.password) { } else if (sself.username && sself.password) {
operation.credential = [NSURLCredential credentialWithUser:wself.username password:wself.password persistence:NSURLCredentialPersistenceForSession]; operation.credential = [NSURLCredential credentialWithUser:sself.username password:sself.password persistence:NSURLCredentialPersistenceForSession];
} }
if (options & SDWebImageDownloaderHighPriority) { if (options & SDWebImageDownloaderHighPriority) {
@ -150,11 +169,11 @@
operation.queuePriority = NSOperationQueuePriorityLow; operation.queuePriority = NSOperationQueuePriorityLow;
} }
[wself.downloadQueue addOperation:operation]; [sself.downloadQueue addOperation:operation];
if (wself.executionOrder == SDWebImageDownloaderLIFOExecutionOrder) { if (sself.executionOrder == SDWebImageDownloaderLIFOExecutionOrder) {
// Emulate LIFO execution order by systematically adding new operations as last operation's dependency // Emulate LIFO execution order by systematically adding new operations as last operation's dependency
[wself.lastAddedOperation addDependency:operation]; [sself.lastAddedOperation addDependency:operation];
wself.lastAddedOperation = operation; sself.lastAddedOperation = operation;
} }
return operation; return operation;
@ -218,4 +237,66 @@
[self.downloadQueue cancelAllOperations]; [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,22 +15,26 @@ extern NSString *const SDWebImageDownloadReceiveResponseNotification;
extern NSString *const SDWebImageDownloadStopNotification; extern NSString *const SDWebImageDownloadStopNotification;
extern NSString *const SDWebImageDownloadFinishNotification; extern NSString *const SDWebImageDownloadFinishNotification;
@interface SDWebImageDownloaderOperation : NSOperation <SDWebImageOperation> @interface SDWebImageDownloaderOperation : NSOperation <SDWebImageOperation, NSURLSessionTaskDelegate, NSURLSessionDataDelegate>
/** /**
* The request used by the operation's connection. * The request used by the operation's task.
*/ */
@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;
/** /**
* Whether the URL connection should consult the credential storage for authenticating the connection. `YES` by default. * Was used to determine whether the URL connection should consult the credential storage for authenticating the connection.
* * @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; @property (nonatomic, assign) BOOL shouldUseCredentialStorage __deprecated_msg("Property deprecated. Does nothing. Kept only for backwards compatibility");
/** /**
* The credential used for authentication challenges in `-connection:didReceiveAuthenticationChallenge:`. * The credential used for authentication challenges in `-connection:didReceiveAuthenticationChallenge:`.
@ -60,11 +64,13 @@ 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
* *
* @return the initialized instance * @return the initialized instance
*/ */
- (instancetype)initWithRequest:(NSURLRequest *)request - (instancetype)initWithRequest:(NSURLRequest *)request
inSession:(NSURLSession *)session
options:(SDWebImageDownloaderOptions)options NS_DESIGNATED_INITIALIZER; options:(SDWebImageDownloaderOptions)options NS_DESIGNATED_INITIALIZER;
/** /**

View File

@ -20,14 +20,22 @@ NSString *const SDWebImageDownloadFinishNotification = @"SDWebImageDownloadFinis
static NSString *const kProgressCallbackKey = @"progress"; static NSString *const kProgressCallbackKey = @"progress";
static NSString *const kCompletedCallbackKey = @"completed"; static NSString *const kCompletedCallbackKey = @"completed";
@interface SDWebImageDownloaderOperation () <NSURLConnectionDataDelegate> @interface SDWebImageDownloaderOperation ()
@property (strong, nonatomic) NSMutableArray *callbackBlocks; @property (strong, nonatomic) NSMutableArray *callbackBlocks;
@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;
@property (SDDispatchQueueSetterSementics, nonatomic) dispatch_queue_t barrierQueue; @property (SDDispatchQueueSetterSementics, nonatomic) dispatch_queue_t barrierQueue;
@ -47,23 +55,22 @@ static NSString *const kCompletedCallbackKey = @"completed";
@synthesize finished = _finished; @synthesize finished = _finished;
- (instancetype)init { - (instancetype)init {
if (self = [self initWithRequest:nil options:0]) { return [self initWithRequest:nil inSession:nil options:0];
}
return self;
} }
- (instancetype)initWithRequest:(NSURLRequest *)request - (instancetype)initWithRequest:(NSURLRequest *)request
inSession:(NSURLSession *)session
options:(SDWebImageDownloaderOptions)options { options:(SDWebImageDownloaderOptions)options {
if ((self = [super init])) { if ((self = [super init])) {
_request = request; _request = request;
_shouldDecompressImages = YES; _shouldDecompressImages = YES;
_shouldUseCredentialStorage = YES;
_options = options; _options = options;
_callbackBlocks = [NSMutableArray new]; _callbackBlocks = [NSMutableArray new];
_executing = NO; _executing = NO;
_finished = NO; _finished = NO;
_expectedSize = 0; _expectedSize = 0;
responseFromCached = YES; // Initially wrong until `connection:willCacheResponse:` is called or not called _unownedSession = session;
responseFromCached = YES; // Initially wrong until `- URLSession:dataTask:willCacheResponse:completionHandler: is called or not called
_barrierQueue = dispatch_queue_create("com.hackemist.SDWebImageDownloaderOperationBarrierQueue", DISPATCH_QUEUE_CONCURRENT); _barrierQueue = dispatch_queue_create("com.hackemist.SDWebImageDownloaderOperationBarrierQueue", DISPATCH_QUEUE_CONCURRENT);
} }
return self; return self;
@ -134,38 +141,37 @@ static NSString *const kCompletedCallbackKey = @"completed";
}]; }];
} }
#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];
[self.connection start]; if (self.dataTask) {
if (self.connection) {
for (SDWebImageDownloaderProgressBlock progressBlock in [self callbacksForKey:kProgressCallbackKey]) { for (SDWebImageDownloaderProgressBlock progressBlock in [self callbacksForKey:kProgressCallbackKey]) {
progressBlock(0, NSURLResponseUnknownLength); 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];
}); });
} else {
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 {
for (SDWebImageDownloaderCompletedBlock completedBlock in [self callbacksForKey:kCompletedCallbackKey]) { for (SDWebImageDownloaderCompletedBlock completedBlock in [self callbacksForKey:kCompletedCallbackKey]) {
completedBlock(nil, nil, [NSError errorWithDomain:NSURLErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey : @"Connection can't be initialized"}], YES); completedBlock(nil, nil, [NSError errorWithDomain:NSURLErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey : @"Connection can't be initialized"}], YES);
} }
@ -198,15 +204,14 @@ static NSString *const kCompletedCallbackKey = @"completed";
- (void)cancelInternalAndStop { - (void)cancelInternalAndStop {
if (self.isFinished) return; if (self.isFinished) return;
[self cancelInternal]; [self cancelInternal];
CFRunLoopStop(CFRunLoopGetCurrent());
} }
- (void)cancelInternal { - (void)cancelInternal {
if (self.isFinished) return; if (self.isFinished) return;
[super cancel]; [super cancel];
if (self.connection) { if (self.dataTask) {
[self.connection cancel]; [self.dataTask 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];
}); });
@ -230,9 +235,13 @@ static NSString *const kCompletedCallbackKey = @"completed";
dispatch_barrier_async(self.barrierQueue, ^{ dispatch_barrier_async(self.barrierQueue, ^{
[self.callbackBlocks removeAllObjects]; [self.callbackBlocks removeAllObjects];
}); });
self.connection = nil; self.dataTask = 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 {
@ -251,9 +260,12 @@ static NSString *const kCompletedCallbackKey = @"completed";
return YES; return YES;
} }
#pragma mark NSURLConnection (delegate) #pragma mark NSURLSessionDataDelegate
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { - (void)URLSession:(NSURLSession *)session
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)) {
@ -262,7 +274,7 @@ static NSString *const kCompletedCallbackKey = @"completed";
for (SDWebImageDownloaderProgressBlock progressBlock in [self callbacksForKey:kProgressCallbackKey]) { for (SDWebImageDownloaderProgressBlock progressBlock in [self callbacksForKey:kProgressCallbackKey]) {
progressBlock(0, expected); 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(), ^{
@ -277,7 +289,7 @@ static NSString *const kCompletedCallbackKey = @"completed";
if (code == 304) { if (code == 304) {
[self cancelInternal]; [self cancelInternal];
} else { } else {
[self.connection cancel]; [self.dataTask 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];
@ -286,12 +298,15 @@ static NSString *const kCompletedCallbackKey = @"completed";
for (SDWebImageDownloaderCompletedBlock completedBlock in [self callbacksForKey:kCompletedCallbackKey]) { for (SDWebImageDownloaderCompletedBlock completedBlock in [self callbacksForKey:kCompletedCallbackKey]) {
completedBlock(nil, nil, [NSError errorWithDomain:NSURLErrorDomain code:((NSHTTPURLResponse *)response).statusCode userInfo:nil], YES); completedBlock(nil, nil, [NSError errorWithDomain:NSURLErrorDomain code:((NSHTTPURLResponse *)response).statusCode userInfo:nil], YES);
} }
CFRunLoopStop(CFRunLoopGetCurrent());
[self done]; [self done];
} }
if (completionHandler) {
completionHandler(NSURLSessionResponseAllow);
}
} }
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {
[self.imageData appendData:data]; [self.imageData appendData:data];
if ((self.options & SDWebImageDownloaderProgressiveDownload) && self.expectedSize > 0) { if ((self.options & SDWebImageDownloaderProgressiveDownload) && self.expectedSize > 0) {
@ -319,10 +334,9 @@ static NSString *const kCompletedCallbackKey = @"completed";
// 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 connectionDidFinishLoading.) So save it here and pass it on later. // in didCompleteWithError.) 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)];
} }
} }
if (width + height > 0 && totalSize < self.expectedSize) { if (width + height > 0 && totalSize < self.expectedSize) {
@ -376,6 +390,114 @@ static NSString *const kCompletedCallbackKey = @"completed";
} }
} }
- (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 {
NSArray *completionBlocks = [[self callbacksForKey:kCompletedCallbackKey] copy];
@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) {
for (SDWebImageDownloaderCompletedBlock completionBlock in completionBlocks) {
completionBlock(nil, nil, error, YES);
}
} else {
if (![[NSURLCache sharedURLCache] cachedResponseForRequest:_request]) {
responseFromCached = NO;
}
if (completionBlocks.count > 0) {
if (self.options & SDWebImageDownloaderIgnoreCachedResponse && responseFromCached) {
for (SDWebImageDownloaderCompletedBlock completionBlock in completionBlocks) {
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)) {
for (SDWebImageDownloaderCompletedBlock completionBlock in completionBlocks) {
completionBlock(nil, nil, [NSError errorWithDomain:SDWebImageErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey : @"Downloaded image has 0 pixels"}], YES);
}
} else {
for (SDWebImageDownloaderCompletedBlock completionBlock in completionBlocks) {
completionBlock(image, self.imageData, nil, YES);
}
}
} else {
for (SDWebImageDownloaderCompletedBlock completionBlock in completionBlocks) {
completionBlock(nil, nil, [NSError errorWithDomain:SDWebImageErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey : @"Image data is nil"}], YES);
}
}
}
}
[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:
@ -403,111 +525,8 @@ static NSString *const kCompletedCallbackKey = @"completed";
return SDScaledImageForKey(key, image); return SDScaledImageForKey(key, image);
} }
- (void)connectionDidFinishLoading:(NSURLConnection *)aConnection {
NSArray *completionBlocks = [[self callbacksForKey:kCompletedCallbackKey] copy];
@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 (completionBlocks.count > 0) {
if (self.options & SDWebImageDownloaderIgnoreCachedResponse && responseFromCached) {
for (SDWebImageDownloaderCompletedBlock completionBlock in completionBlocks) {
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];
}
}
for (SDWebImageDownloaderCompletedBlock completionBlock in completionBlocks) {
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 {
for (SDWebImageDownloaderCompletedBlock completionBlock in completionBlocks) {
completionBlock(nil, nil, [NSError errorWithDomain:SDWebImageErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey : @"Image data is nil"}], YES);
}
}
}
[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];
});
}
for (SDWebImageDownloaderCompletedBlock completedBlock in [self callbacksForKey:kCompletedCallbackKey]) {
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

@ -54,14 +54,17 @@
} }
- (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 {
if (NSClassFromString(@"NSURLComponents") && [NSURLComponents instancesRespondToSelector:@selector(string)]) { if (NSClassFromString(@"NSURLComponents") && [NSURLComponents instancesRespondToSelector:@selector(string)]) {
NSURLComponents *urlComponents = [[NSURLComponents alloc] initWithURL:url resolvingAgainstBaseURL:NO]; NSURLComponents *urlComponents = [[NSURLComponents alloc] initWithURL:url resolvingAgainstBaseURL:NO];
urlComponents.query = nil; // Strip out query parameters. urlComponents.query = nil; // Strip out query parameters.
return urlComponents.string; return urlComponents.URL.absoluteString;
} else { } else {
return url.absoluteString; return url.absoluteString;
} }

View File

@ -1,10 +1,11 @@
// /*
// UIImage+GIF.h * This file is part of the SDWebImage package.
// LBGIFImage * (c) Olivier Poitrey <rs@dailymotion.com>
// * (c) Laurin Brandner
// Created by Laurin Brandner on 06.01.12. *
// Copyright (c) 2012 __MyCompanyName__. All rights reserved. * For the full copyright and license information, please view the LICENSE
// * file that was distributed with this source code.
*/
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>

View File

@ -1,10 +1,11 @@
// /*
// UIImage+GIF.m * This file is part of the SDWebImage package.
// LBGIFImage * (c) Olivier Poitrey <rs@dailymotion.com>
// * (c) Laurin Brandner
// Created by Laurin Brandner on 06.01.12. *
// Copyright (c) 2012 __MyCompanyName__. All rights reserved. * For the full copyright and license information, please view the LICENSE
// * file that was distributed with this source code.
*/
#import "UIImage+GIF.h" #import "UIImage+GIF.h"
#import <ImageIO/ImageIO.h> #import <ImageIO/ImageIO.h>

View File

@ -1,10 +1,10 @@
// /*
// UIImage+MultiFormat.h * This file is part of the SDWebImage package.
// SDWebImage * (c) Olivier Poitrey <rs@dailymotion.com>
// *
// Created by Olivier Poitrey on 07/06/13. * For the full copyright and license information, please view the LICENSE
// Copyright (c) 2013 Dailymotion. All rights reserved. * file that was distributed with this source code.
// */
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>

View File

@ -1,10 +1,10 @@
// /*
// UIImage+MultiFormat.m * This file is part of the SDWebImage package.
// SDWebImage * (c) Olivier Poitrey <rs@dailymotion.com>
// *
// Created by Olivier Poitrey on 07/06/13. * For the full copyright and license information, please view the LICENSE
// Copyright (c) 2013 Dailymotion. All rights reserved. * file that was distributed with this source code.
// */
#import "UIImage+MultiFormat.h" #import "UIImage+MultiFormat.h"
#import "UIImage+GIF.h" #import "UIImage+GIF.h"

View File

@ -1,10 +1,10 @@
// /*
// UIImage+WebP.h * This file is part of the SDWebImage package.
// SDWebImage * (c) Olivier Poitrey <rs@dailymotion.com>
// *
// Created by Olivier Poitrey on 07/06/13. * For the full copyright and license information, please view the LICENSE
// Copyright (c) 2013 Dailymotion. All rights reserved. * file that was distributed with this source code.
// */
#ifdef SD_WEBP #ifdef SD_WEBP

View File

@ -1,10 +1,10 @@
// /*
// UIImage+WebP.m * This file is part of the SDWebImage package.
// SDWebImage * (c) Olivier Poitrey <rs@dailymotion.com>
// *
// Created by Olivier Poitrey on 07/06/13. * For the full copyright and license information, please view the LICENSE
// Copyright (c) 2013 Dailymotion. All rights reserved. * file that was distributed with this source code.
// */
#ifdef SD_WEBP #ifdef SD_WEBP
#import "UIImage+WebP.h" #import "UIImage+WebP.h"

View File

@ -4,7 +4,7 @@ xcodeproj 'SDWebImage Tests'
workspace '../SDWebImage' workspace '../SDWebImage'
target 'Tests' do target 'Tests' do
platform :ios, '5.0' platform :ios, '7.0'
pod 'Expecta', '<=0.3.1' pod 'Expecta', '<=0.3.1'
pod 'SDWebImage', :path => '../' pod 'SDWebImage', :path => '../'

View File

@ -8,8 +8,8 @@
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
0D87E1F83BD319CEC7622E9F /* libPods-Tests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0462A7F023A057322E59B3C5 /* libPods-Tests.a */; }; 0D87E1F83BD319CEC7622E9F /* libPods-Tests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0462A7F023A057322E59B3C5 /* libPods-Tests.a */; };
5F7F38AD1AE2A77A00B0E330 /* TestImage.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 5F7F38AC1AE2A77A00B0E330 /* TestImage.jpg */; };
1E3C51E919B46E370092B5E6 /* SDWebImageDownloaderTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E3C51E819B46E370092B5E6 /* SDWebImageDownloaderTests.m */; }; 1E3C51E919B46E370092B5E6 /* SDWebImageDownloaderTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E3C51E819B46E370092B5E6 /* SDWebImageDownloaderTests.m */; };
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 */; };
@ -21,10 +21,10 @@
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
0462A7F023A057322E59B3C5 /* libPods-Tests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Tests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 0462A7F023A057322E59B3C5 /* libPods-Tests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Tests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
1E3C51E819B46E370092B5E6 /* SDWebImageDownloaderTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDWebImageDownloaderTests.m; sourceTree = "<group>"; };
5F7F38AC1AE2A77A00B0E330 /* TestImage.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = TestImage.jpg; sourceTree = "<group>"; }; 5F7F38AC1AE2A77A00B0E330 /* TestImage.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = TestImage.jpg; sourceTree = "<group>"; };
700B00151041D7EE118B1ABD /* 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>"; }; 700B00151041D7EE118B1ABD /* 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>"; };
A0085854E7D88C98F2F6C9FC /* 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>"; }; A0085854E7D88C98F2F6C9FC /* 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>"; };
1E3C51E819B46E370092B5E6 /* SDWebImageDownloaderTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDWebImageDownloaderTests.m; 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; };
@ -251,7 +251,7 @@
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
ENABLE_TESTABILITY = YES; ENABLE_TESTABILITY = YES;
IPHONEOS_DEPLOYMENT_TARGET = 6.0; IPHONEOS_DEPLOYMENT_TARGET = 7.0;
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
}; };
name = Debug; name = Debug;
@ -259,7 +259,7 @@
DA248D4B1954721A00390AB0 /* Release */ = { DA248D4B1954721A00390AB0 /* Release */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
IPHONEOS_DEPLOYMENT_TARGET = 6.0; IPHONEOS_DEPLOYMENT_TARGET = 7.0;
}; };
name = Release; name = Release;
}; };

View File

@ -1,10 +1,10 @@
// /*
// SDImageCacheTests.m * This file is part of the SDWebImage package.
// SDWebImage Tests * (c) Olivier Poitrey <rs@dailymotion.com>
// *
// Created by Bogdan Poplauschi on 20/06/14. * For the full copyright and license information, please view the LICENSE
// * file that was distributed with this source code.
// */
#define EXP_SHORTHAND // required by Expecta #define EXP_SHORTHAND // required by Expecta

View File

@ -1,10 +1,11 @@
// /*
// SDWebImageDownloaderTests.m * This file is part of the SDWebImage package.
// SDWebImage Tests * (c) Olivier Poitrey <rs@dailymotion.com>
// * (c) Matt Galloway
// Created by Matt Galloway on 01/09/2014. *
// * For the full copyright and license information, please view the LICENSE
// * file that was distributed with this source code.
*/
#define EXP_SHORTHAND // required by Expecta #define EXP_SHORTHAND // required by Expecta

View File

@ -1,10 +1,10 @@
// /*
// SDWebImageManagerTests.m * This file is part of the SDWebImage package.
// SDWebImage Tests * (c) Olivier Poitrey <rs@dailymotion.com>
// *
// Created by Bogdan Poplauschi on 20/06/14. * For the full copyright and license information, please view the LICENSE
// * file that was distributed with this source code.
// */
#define EXP_SHORTHAND // required by Expecta #define EXP_SHORTHAND // required by Expecta

View File

@ -1,10 +1,10 @@
// /*
// UIImageMultiFormatTests.m * This file is part of the SDWebImage package.
// SDWebImage Tests * (c) Olivier Poitrey <rs@dailymotion.com>
// *
// Created by Bogdan Poplauschi on 18/07/14. * For the full copyright and license information, please view the LICENSE
// * file that was distributed with this source code.
// */
#define EXP_SHORTHAND // required by Expecta #define EXP_SHORTHAND // required by Expecta

View File

@ -15,7 +15,7 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>FMWK</string> <string>FMWK</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>3.7.6</string> <string>3.8.0</string>
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>????</string> <string>????</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>

View File

@ -1,10 +1,11 @@
// /*
// WebImage.h * This file is part of the SDWebImage package.
// WebImage * (c) Olivier Poitrey <rs@dailymotion.com>
// * (c) Florent Vilmart
// Created by Florent Vilmart on 2015-03-14. *
// Copyright (c) 2015 Dailymotion. All rights reserved. * For the full copyright and license information, please view the LICENSE
// * file that was distributed with this source code.
*/
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>