diff --git a/.travis.yml b/.travis.yml index 986ce3c8..4f7979c9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -39,4 +39,4 @@ script: - echo Run the tests - pod install --project-directory=Tests - 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 \ No newline at end of file + - xcodebuild test -workspace SDWebImage.xcworkspace -scheme 'Tests' -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 6,OS=latest' -configuration Debug | xcpretty -c diff --git a/CHANGELOG.md b/CHANGELOG.md index 553f102f..adefeb16 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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) #### Infrastructure: diff --git a/Examples/SDWebImage Demo.xcodeproj/project.pbxproj b/Examples/SDWebImage Demo.xcodeproj/project.pbxproj index 191729e7..85b45889 100644 --- a/Examples/SDWebImage Demo.xcodeproj/project.pbxproj +++ b/Examples/SDWebImage Demo.xcodeproj/project.pbxproj @@ -323,7 +323,7 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 6.0; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; }; @@ -341,7 +341,7 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 6.0; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; diff --git a/Examples/SDWebImage Demo/AppDelegate.h b/Examples/SDWebImage Demo/AppDelegate.h index 7e60e229..15f2cc6e 100644 --- a/Examples/SDWebImage Demo/AppDelegate.h +++ b/Examples/SDWebImage Demo/AppDelegate.h @@ -1,10 +1,10 @@ -// -// AppDelegate.h -// SDWebImage Demo -// -// Created by Olivier Poitrey on 09/05/12. -// Copyright (c) 2012 Dailymotion. All rights reserved. -// +/* + * This file is part of the SDWebImage package. + * (c) Olivier Poitrey + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ #import diff --git a/Examples/SDWebImage Demo/AppDelegate.m b/Examples/SDWebImage Demo/AppDelegate.m index 4ddd8e64..a7c47598 100644 --- a/Examples/SDWebImage Demo/AppDelegate.m +++ b/Examples/SDWebImage Demo/AppDelegate.m @@ -1,10 +1,10 @@ -// -// AppDelegate.m -// SDWebImage Demo -// -// Created by Olivier Poitrey on 09/05/12. -// Copyright (c) 2012 Dailymotion. All rights reserved. -// +/* + * This file is part of the SDWebImage package. + * (c) Olivier Poitrey + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ #import "AppDelegate.h" diff --git a/Examples/SDWebImage Demo/DetailViewController.h b/Examples/SDWebImage Demo/DetailViewController.h index 1272c090..d0e6588d 100644 --- a/Examples/SDWebImage Demo/DetailViewController.h +++ b/Examples/SDWebImage Demo/DetailViewController.h @@ -1,10 +1,10 @@ -// -// DetailViewController.h -// SDWebImage Demo -// -// Created by Olivier Poitrey on 09/05/12. -// Copyright (c) 2012 Dailymotion. All rights reserved. -// +/* + * This file is part of the SDWebImage package. + * (c) Olivier Poitrey + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ #import diff --git a/Examples/SDWebImage Demo/DetailViewController.m b/Examples/SDWebImage Demo/DetailViewController.m index da57ed71..c9df0745 100644 --- a/Examples/SDWebImage Demo/DetailViewController.m +++ b/Examples/SDWebImage Demo/DetailViewController.m @@ -1,10 +1,10 @@ -// -// DetailViewController.m -// SDWebImage Demo -// -// Created by Olivier Poitrey on 09/05/12. -// Copyright (c) 2012 Dailymotion. All rights reserved. -// +/* + * This file is part of the SDWebImage package. + * (c) Olivier Poitrey + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ #import "DetailViewController.h" #import diff --git a/Examples/SDWebImage Demo/MasterViewController.h b/Examples/SDWebImage Demo/MasterViewController.h index 3f3a1392..96983d10 100644 --- a/Examples/SDWebImage Demo/MasterViewController.h +++ b/Examples/SDWebImage Demo/MasterViewController.h @@ -1,10 +1,10 @@ -// -// MasterViewController.h -// SDWebImage Demo -// -// Created by Olivier Poitrey on 09/05/12. -// Copyright (c) 2012 Dailymotion. All rights reserved. -// +/* + * This file is part of the SDWebImage package. + * (c) Olivier Poitrey + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ #import diff --git a/Examples/SDWebImage Demo/MasterViewController.m b/Examples/SDWebImage Demo/MasterViewController.m index 4e580ccc..57327de6 100644 --- a/Examples/SDWebImage Demo/MasterViewController.m +++ b/Examples/SDWebImage Demo/MasterViewController.m @@ -1,10 +1,10 @@ -// -// MasterViewController.m -// SDWebImage Demo -// -// Created by Olivier Poitrey on 09/05/12. -// Copyright (c) 2012 Dailymotion. All rights reserved. -// +/* + * This file is part of the SDWebImage package. + * (c) Olivier Poitrey + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ #import "MasterViewController.h" #import diff --git a/Examples/SDWebImage Demo/main.m b/Examples/SDWebImage Demo/main.m index 463372ca..1d5fab2c 100644 --- a/Examples/SDWebImage Demo/main.m +++ b/Examples/SDWebImage Demo/main.m @@ -1,10 +1,10 @@ -// -// main.m -// SDWebImage Demo -// -// Created by Olivier Poitrey on 09/05/12. -// Copyright (c) 2012 Dailymotion. All rights reserved. -// +/* + * This file is part of the SDWebImage package. + * (c) Olivier Poitrey + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ #import diff --git a/README.md b/README.md index bf9c4903..35830601 100644 --- a/README.md +++ b/README.md @@ -120,8 +120,8 @@ There are three ways to use SDWebImage in your project: #### Podfile ``` -platform :ios, '6.1' -pod 'SDWebImage', '~>3.7' +platform :ios, '7.0' +pod 'SDWebImage', '~>3.8' ``` If you are using Swift, be sure to add `use_frameworks!` and set your target to iOS 8+: diff --git a/SDWebImage.podspec b/SDWebImage.podspec index 0aab1a63..34bb4e45 100644 --- a/SDWebImage.podspec +++ b/SDWebImage.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = 'SDWebImage' - s.version = '3.7.6' - s.ios.deployment_target = '5.0' + s.version = '3.8.0' + s.ios.deployment_target = '7.0' s.tvos.deployment_target = '9.0' s.license = 'MIT' s.summary = 'Asynchronous image downloader with cache support with an UIImageView category.' @@ -29,7 +29,7 @@ Pod::Spec.new do |s| end s.subspec 'MapKit' do |mk| - mk.ios.deployment_target = '5.0' + mk.ios.deployment_target = '7.0' mk.source_files = 'SDWebImage/MKAnnotationView+WebCache.*' mk.framework = 'MapKit' mk.dependency 'SDWebImage/Core' diff --git a/SDWebImage.xcodeproj/project.pbxproj b/SDWebImage.xcodeproj/project.pbxproj index 2198a5f0..63784168 100644 --- a/SDWebImage.xcodeproj/project.pbxproj +++ b/SDWebImage.xcodeproj/project.pbxproj @@ -1469,7 +1469,7 @@ GCC_WARN_UNUSED_PARAMETER = NO; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = Vendors/libwebp/src; - IPHONEOS_DEPLOYMENT_TARGET = 6.0; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; ONLY_ACTIVE_ARCH = YES; OTHER_LDFLAGS = "-ObjC"; RUN_CLANG_STATIC_ANALYZER = YES; @@ -1524,7 +1524,7 @@ GCC_WARN_UNUSED_PARAMETER = NO; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = Vendors/libwebp/src; - IPHONEOS_DEPLOYMENT_TARGET = 6.0; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; OTHER_LDFLAGS = "-ObjC"; RUN_CLANG_STATIC_ANALYZER = YES; SDKROOT = iphoneos; diff --git a/SDWebImage/MKAnnotationView+WebCache.h b/SDWebImage/MKAnnotationView+WebCache.h index 8f87f2e3..eebbaba4 100644 --- a/SDWebImage/MKAnnotationView+WebCache.h +++ b/SDWebImage/MKAnnotationView+WebCache.h @@ -1,10 +1,10 @@ -// -// MKAnnotationView+WebCache.h -// SDWebImage -// -// Created by Olivier Poitrey on 14/03/12. -// Copyright (c) 2012 Dailymotion. All rights reserved. -// +/* + * This file is part of the SDWebImage package. + * (c) Olivier Poitrey + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ #import "MapKit/MapKit.h" #import "SDWebImageManager.h" diff --git a/SDWebImage/MKAnnotationView+WebCache.m b/SDWebImage/MKAnnotationView+WebCache.m index 398183f4..bf8297dd 100644 --- a/SDWebImage/MKAnnotationView+WebCache.m +++ b/SDWebImage/MKAnnotationView+WebCache.m @@ -1,10 +1,10 @@ -// -// MKAnnotationView+WebCache.m -// SDWebImage -// -// Created by Olivier Poitrey on 14/03/12. -// Copyright (c) 2012 Dailymotion. All rights reserved. -// +/* + * This file is part of the SDWebImage package. + * (c) Olivier Poitrey + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ #import "MKAnnotationView+WebCache.h" #import "objc/runtime.h" diff --git a/SDWebImage/NSData+ImageContentType.h b/SDWebImage/NSData+ImageContentType.h index f6d452f0..3a1a9f39 100644 --- a/SDWebImage/NSData+ImageContentType.h +++ b/SDWebImage/NSData+ImageContentType.h @@ -1,7 +1,11 @@ -// -// Created by Fabrice Aneche on 06/01/14. -// Copyright (c) 2014 Dailymotion. All rights reserved. -// +/* + * This file is part of the SDWebImage package. + * (c) Olivier Poitrey + * (c) Fabrice Aneche + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ #import diff --git a/SDWebImage/NSData+ImageContentType.m b/SDWebImage/NSData+ImageContentType.m index beb73b59..0d3c1e8f 100644 --- a/SDWebImage/NSData+ImageContentType.m +++ b/SDWebImage/NSData+ImageContentType.m @@ -1,7 +1,11 @@ -// -// Created by Fabrice Aneche on 06/01/14. -// Copyright (c) 2014 Dailymotion. All rights reserved. -// +/* + * This file is part of the SDWebImage package. + * (c) Olivier Poitrey + * (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" diff --git a/SDWebImage/SDWebImageCompat.m b/SDWebImage/SDWebImageCompat.m index 3de79f4e..958bed65 100644 --- a/SDWebImage/SDWebImageCompat.m +++ b/SDWebImage/SDWebImageCompat.m @@ -1,10 +1,10 @@ -// -// SDWebImageCompat.m -// SDWebImage -// -// Created by Olivier Poitrey on 11/12/12. -// Copyright (c) 2012 Dailymotion. All rights reserved. -// +/* + * This file is part of the SDWebImage package. + * (c) Olivier Poitrey + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ #import "SDWebImageCompat.h" diff --git a/SDWebImage/SDWebImageDecoder.h b/SDWebImage/SDWebImageDecoder.h index 0176a7ba..2bfe7b4d 100644 --- a/SDWebImage/SDWebImageDecoder.h +++ b/SDWebImage/SDWebImageDecoder.h @@ -1,8 +1,7 @@ /* * This file is part of the SDWebImage package. * (c) Olivier Poitrey - * - * Created by james on 9/28/11. + * (c) james * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. diff --git a/SDWebImage/SDWebImageDecoder.m b/SDWebImage/SDWebImageDecoder.m index 2bb5472f..e5d7b910 100644 --- a/SDWebImage/SDWebImageDecoder.m +++ b/SDWebImage/SDWebImageDecoder.m @@ -1,8 +1,7 @@ /* * This file is part of the SDWebImage package. * (c) Olivier Poitrey - * - * Created by james on 9/28/11. + * (c) james * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. diff --git a/SDWebImage/SDWebImageDownloader.m b/SDWebImage/SDWebImageDownloader.m index 5355765c..70b2d51d 100644 --- a/SDWebImage/SDWebImageDownloader.m +++ b/SDWebImage/SDWebImageDownloader.m @@ -14,7 +14,7 @@ @end -@interface SDWebImageDownloader () +@interface SDWebImageDownloader () @property (strong, nonatomic) NSOperationQueue *downloadQueue; @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 @property (SDDispatchQueueSetterSementics, nonatomic) dispatch_queue_t barrierQueue; +// The session in which data tasks will run +@property (strong, nonatomic) NSURLSession *session; + @end @implementation SDWebImageDownloader @@ -75,11 +78,26 @@ #endif _barrierQueue = dispatch_queue_create("com.hackemist.SDWebImageDownloaderBarrierQueue", DISPATCH_QUEUE_CONCURRENT); _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; } - (void)dealloc { + [self.session invalidateAndCancel]; + self.session = nil; + [self.downloadQueue cancelAllOperations]; SDDispatchQueueRelease(_barrierQueue); } @@ -120,7 +138,8 @@ __weak SDWebImageDownloader *wself = self; 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) { timeoutInterval = 15.0; } @@ -129,19 +148,19 @@ NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url cachePolicy:(options & SDWebImageDownloaderUseNSURLCache ? NSURLRequestUseProtocolCachePolicy : NSURLRequestReloadIgnoringLocalCacheData) timeoutInterval:timeoutInterval]; request.HTTPShouldHandleCookies = (options & SDWebImageDownloaderHandleCookies); request.HTTPShouldUsePipelining = YES; - if (wself.headersFilter) { - request.allHTTPHeaderFields = wself.headersFilter(url, [wself.HTTPHeaders copy]); + if (sself.headersFilter) { + request.allHTTPHeaderFields = sself.headersFilter(url, [sself.HTTPHeaders copy]); } else { - request.allHTTPHeaderFields = wself.HTTPHeaders; + request.allHTTPHeaderFields = sself.HTTPHeaders; } - SDWebImageDownloaderOperation *operation = [[wself.operationClass alloc] initWithRequest:request options:options]; - operation.shouldDecompressImages = wself.shouldDecompressImages; + SDWebImageDownloaderOperation *operation = [[sself.operationClass alloc] initWithRequest:request inSession:sself.session options:options]; + operation.shouldDecompressImages = sself.shouldDecompressImages; - if (wself.urlCredential) { - operation.credential = wself.urlCredential; - } else if (wself.username && wself.password) { - operation.credential = [NSURLCredential credentialWithUser:wself.username password:wself.password persistence:NSURLCredentialPersistenceForSession]; + if (sself.urlCredential) { + operation.credential = sself.urlCredential; + } else if (sself.username && sself.password) { + operation.credential = [NSURLCredential credentialWithUser:sself.username password:sself.password persistence:NSURLCredentialPersistenceForSession]; } if (options & SDWebImageDownloaderHighPriority) { @@ -150,11 +169,11 @@ operation.queuePriority = NSOperationQueuePriorityLow; } - [wself.downloadQueue addOperation:operation]; - if (wself.executionOrder == SDWebImageDownloaderLIFOExecutionOrder) { + [sself.downloadQueue addOperation:operation]; + if (sself.executionOrder == SDWebImageDownloaderLIFOExecutionOrder) { // Emulate LIFO execution order by systematically adding new operations as last operation's dependency - [wself.lastAddedOperation addDependency:operation]; - wself.lastAddedOperation = operation; + [sself.lastAddedOperation addDependency:operation]; + sself.lastAddedOperation = operation; } return operation; @@ -218,4 +237,66 @@ [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 diff --git a/SDWebImage/SDWebImageDownloaderOperation.h b/SDWebImage/SDWebImageDownloaderOperation.h index 69763afa..34f42291 100644 --- a/SDWebImage/SDWebImageDownloaderOperation.h +++ b/SDWebImage/SDWebImageDownloaderOperation.h @@ -15,22 +15,26 @@ extern NSString *const SDWebImageDownloadReceiveResponseNotification; extern NSString *const SDWebImageDownloadStopNotification; extern NSString *const SDWebImageDownloadFinishNotification; -@interface SDWebImageDownloaderOperation : NSOperation +@interface SDWebImageDownloaderOperation : NSOperation /** - * The request used by the operation's connection. + * The request used by the operation's task. */ @property (strong, nonatomic, readonly) NSURLRequest *request; +/** + * The operation's task + */ +@property (strong, nonatomic, readonly) NSURLSessionTask *dataTask; + @property (assign, nonatomic) BOOL shouldDecompressImages; /** - * Whether the URL connection should consult the credential storage for authenticating the connection. `YES` by default. - * - * This is the value that is returned in the `NSURLConnectionDelegate` method `-connectionShouldUseCredentialStorage:`. + * 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 */ -@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:`. @@ -60,11 +64,13 @@ extern NSString *const SDWebImageDownloadFinishNotification; * @see SDWebImageDownloaderOperation * * @param request the URL request + * @param session the URL session in which this operation will run * @param options downloader options * * @return the initialized instance */ - (instancetype)initWithRequest:(NSURLRequest *)request + inSession:(NSURLSession *)session options:(SDWebImageDownloaderOptions)options NS_DESIGNATED_INITIALIZER; /** diff --git a/SDWebImage/SDWebImageDownloaderOperation.m b/SDWebImage/SDWebImageDownloaderOperation.m index 38844c5e..eb40c72d 100644 --- a/SDWebImage/SDWebImageDownloaderOperation.m +++ b/SDWebImage/SDWebImageDownloaderOperation.m @@ -20,14 +20,22 @@ NSString *const SDWebImageDownloadFinishNotification = @"SDWebImageDownloadFinis static NSString *const kProgressCallbackKey = @"progress"; static NSString *const kCompletedCallbackKey = @"completed"; -@interface SDWebImageDownloaderOperation () +@interface SDWebImageDownloaderOperation () @property (strong, nonatomic) NSMutableArray *callbackBlocks; @property (assign, nonatomic, getter = isExecuting) BOOL executing; @property (assign, nonatomic, getter = isFinished) BOOL finished; @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 (SDDispatchQueueSetterSementics, nonatomic) dispatch_queue_t barrierQueue; @@ -47,23 +55,22 @@ static NSString *const kCompletedCallbackKey = @"completed"; @synthesize finished = _finished; - (instancetype)init { - if (self = [self initWithRequest:nil options:0]) { - } - return self; + return [self initWithRequest:nil inSession:nil options:0]; } - (instancetype)initWithRequest:(NSURLRequest *)request + inSession:(NSURLSession *)session options:(SDWebImageDownloaderOptions)options { if ((self = [super init])) { _request = request; _shouldDecompressImages = YES; - _shouldUseCredentialStorage = YES; _options = options; _callbackBlocks = [NSMutableArray new]; _executing = NO; _finished = NO; _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); } return self; @@ -134,38 +141,37 @@ static NSString *const kCompletedCallbackKey = @"completed"; }]; } #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.connection = [[NSURLConnection alloc] initWithRequest:self.request delegate:self startImmediately:NO]; self.thread = [NSThread currentThread]; } + + [self.dataTask resume]; - [self.connection start]; - - if (self.connection) { + if (self.dataTask) { for (SDWebImageDownloaderProgressBlock progressBlock in [self callbacksForKey:kProgressCallbackKey]) { progressBlock(0, NSURLResponseUnknownLength); } dispatch_async(dispatch_get_main_queue(), ^{ [[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 { for (SDWebImageDownloaderCompletedBlock completedBlock in [self callbacksForKey:kCompletedCallbackKey]) { 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 { if (self.isFinished) return; [self cancelInternal]; - CFRunLoopStop(CFRunLoopGetCurrent()); } - (void)cancelInternal { if (self.isFinished) return; [super cancel]; - if (self.connection) { - [self.connection cancel]; + if (self.dataTask) { + [self.dataTask cancel]; dispatch_async(dispatch_get_main_queue(), ^{ [[NSNotificationCenter defaultCenter] postNotificationName:SDWebImageDownloadStopNotification object:self]; }); @@ -230,9 +235,13 @@ static NSString *const kCompletedCallbackKey = @"completed"; dispatch_barrier_async(self.barrierQueue, ^{ [self.callbackBlocks removeAllObjects]; }); - self.connection = nil; + self.dataTask = nil; self.imageData = nil; self.thread = nil; + if (self.ownedSession) { + [self.ownedSession invalidateAndCancel]; + self.ownedSession = nil; + } } - (void)setFinished:(BOOL)finished { @@ -251,9 +260,12 @@ static NSString *const kCompletedCallbackKey = @"completed"; 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 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]) { progressBlock(0, expected); } - + self.imageData = [[NSMutableData alloc] initWithCapacity:expected]; self.response = response; dispatch_async(dispatch_get_main_queue(), ^{ @@ -277,7 +289,7 @@ static NSString *const kCompletedCallbackKey = @"completed"; if (code == 304) { [self cancelInternal]; } else { - [self.connection cancel]; + [self.dataTask cancel]; } dispatch_async(dispatch_get_main_queue(), ^{ [[NSNotificationCenter defaultCenter] postNotificationName:SDWebImageDownloadStopNotification object:self]; @@ -286,12 +298,15 @@ static NSString *const kCompletedCallbackKey = @"completed"; for (SDWebImageDownloaderCompletedBlock completedBlock in [self callbacksForKey:kCompletedCallbackKey]) { completedBlock(nil, nil, [NSError errorWithDomain:NSURLErrorDomain code:((NSHTTPURLResponse *)response).statusCode userInfo:nil], YES); } - CFRunLoopStop(CFRunLoopGetCurrent()); [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]; 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, // which means the image below born of initWithCGIImage will be // 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)]; } - } 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 { switch (value) { case 1: @@ -403,111 +525,8 @@ static NSString *const kCompletedCallbackKey = @"completed"; 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 { 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 diff --git a/SDWebImage/SDWebImageManager.m b/SDWebImage/SDWebImageManager.m index 20bcb65c..92227f63 100644 --- a/SDWebImage/SDWebImageManager.m +++ b/SDWebImage/SDWebImageManager.m @@ -54,14 +54,17 @@ } - (NSString *)cacheKeyForURL:(NSURL *)url { + if (!url) { + return @""; + } + if (self.cacheKeyFilter) { return self.cacheKeyFilter(url); - } - else { + } else { if (NSClassFromString(@"NSURLComponents") && [NSURLComponents instancesRespondToSelector:@selector(string)]) { NSURLComponents *urlComponents = [[NSURLComponents alloc] initWithURL:url resolvingAgainstBaseURL:NO]; urlComponents.query = nil; // Strip out query parameters. - return urlComponents.string; + return urlComponents.URL.absoluteString; } else { return url.absoluteString; } diff --git a/SDWebImage/UIImage+GIF.h b/SDWebImage/UIImage+GIF.h index 97a9893f..63cb856d 100755 --- a/SDWebImage/UIImage+GIF.h +++ b/SDWebImage/UIImage+GIF.h @@ -1,10 +1,11 @@ -// -// UIImage+GIF.h -// LBGIFImage -// -// Created by Laurin Brandner on 06.01.12. -// Copyright (c) 2012 __MyCompanyName__. All rights reserved. -// +/* + * This file is part of the SDWebImage package. + * (c) Olivier Poitrey + * (c) Laurin Brandner + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ #import diff --git a/SDWebImage/UIImage+GIF.m b/SDWebImage/UIImage+GIF.m index bf666113..37c5130b 100755 --- a/SDWebImage/UIImage+GIF.m +++ b/SDWebImage/UIImage+GIF.m @@ -1,10 +1,11 @@ -// -// UIImage+GIF.m -// LBGIFImage -// -// Created by Laurin Brandner on 06.01.12. -// Copyright (c) 2012 __MyCompanyName__. All rights reserved. -// +/* + * This file is part of the SDWebImage package. + * (c) Olivier Poitrey + * (c) Laurin Brandner + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ #import "UIImage+GIF.h" #import diff --git a/SDWebImage/UIImage+MultiFormat.h b/SDWebImage/UIImage+MultiFormat.h index 186ebc0a..e05c111b 100644 --- a/SDWebImage/UIImage+MultiFormat.h +++ b/SDWebImage/UIImage+MultiFormat.h @@ -1,10 +1,10 @@ -// -// UIImage+MultiFormat.h -// SDWebImage -// -// Created by Olivier Poitrey on 07/06/13. -// Copyright (c) 2013 Dailymotion. All rights reserved. -// +/* + * This file is part of the SDWebImage package. + * (c) Olivier Poitrey + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ #import diff --git a/SDWebImage/UIImage+MultiFormat.m b/SDWebImage/UIImage+MultiFormat.m index a8307544..178e9048 100644 --- a/SDWebImage/UIImage+MultiFormat.m +++ b/SDWebImage/UIImage+MultiFormat.m @@ -1,10 +1,10 @@ -// -// UIImage+MultiFormat.m -// SDWebImage -// -// Created by Olivier Poitrey on 07/06/13. -// Copyright (c) 2013 Dailymotion. All rights reserved. -// +/* + * This file is part of the SDWebImage package. + * (c) Olivier Poitrey + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ #import "UIImage+MultiFormat.h" #import "UIImage+GIF.h" diff --git a/SDWebImage/UIImage+WebP.h b/SDWebImage/UIImage+WebP.h index 48cdf030..dbfb0a90 100644 --- a/SDWebImage/UIImage+WebP.h +++ b/SDWebImage/UIImage+WebP.h @@ -1,10 +1,10 @@ -// -// UIImage+WebP.h -// SDWebImage -// -// Created by Olivier Poitrey on 07/06/13. -// Copyright (c) 2013 Dailymotion. All rights reserved. -// +/* + * This file is part of the SDWebImage package. + * (c) Olivier Poitrey + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ #ifdef SD_WEBP diff --git a/SDWebImage/UIImage+WebP.m b/SDWebImage/UIImage+WebP.m index a7e341f6..9acc03cc 100644 --- a/SDWebImage/UIImage+WebP.m +++ b/SDWebImage/UIImage+WebP.m @@ -1,10 +1,10 @@ -// -// UIImage+WebP.m -// SDWebImage -// -// Created by Olivier Poitrey on 07/06/13. -// Copyright (c) 2013 Dailymotion. All rights reserved. -// +/* + * This file is part of the SDWebImage package. + * (c) Olivier Poitrey + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ #ifdef SD_WEBP #import "UIImage+WebP.h" diff --git a/Tests/Podfile b/Tests/Podfile index f2a66884..ba09b915 100644 --- a/Tests/Podfile +++ b/Tests/Podfile @@ -4,7 +4,7 @@ xcodeproj 'SDWebImage Tests' workspace '../SDWebImage' target 'Tests' do - platform :ios, '5.0' + platform :ios, '7.0' pod 'Expecta', '<=0.3.1' pod 'SDWebImage', :path => '../' diff --git a/Tests/SDWebImage Tests.xcodeproj/project.pbxproj b/Tests/SDWebImage Tests.xcodeproj/project.pbxproj index 5b08344d..2f8b8053 100644 --- a/Tests/SDWebImage Tests.xcodeproj/project.pbxproj +++ b/Tests/SDWebImage Tests.xcodeproj/project.pbxproj @@ -8,8 +8,8 @@ /* Begin PBXBuildFile section */ 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 */; }; + 5F7F38AD1AE2A77A00B0E330 /* TestImage.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 5F7F38AC1AE2A77A00B0E330 /* TestImage.jpg */; }; DA248D57195472AA00390AB0 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA248D56195472AA00390AB0 /* XCTest.framework */; }; DA248D59195472AA00390AB0 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA248D58195472AA00390AB0 /* Foundation.framework */; }; DA248D5B195472AA00390AB0 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA248D5A195472AA00390AB0 /* UIKit.framework */; }; @@ -21,10 +21,10 @@ /* Begin PBXFileReference section */ 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 = ""; }; 5F7F38AC1AE2A77A00B0E330 /* TestImage.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = TestImage.jpg; sourceTree = ""; }; 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 = ""; }; 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 = ""; }; - 1E3C51E819B46E370092B5E6 /* SDWebImageDownloaderTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDWebImageDownloaderTests.m; sourceTree = ""; }; 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; }; 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; buildSettings = { ENABLE_TESTABILITY = YES; - IPHONEOS_DEPLOYMENT_TARGET = 6.0; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; ONLY_ACTIVE_ARCH = YES; }; name = Debug; @@ -259,7 +259,7 @@ DA248D4B1954721A00390AB0 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - IPHONEOS_DEPLOYMENT_TARGET = 6.0; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; }; name = Release; }; diff --git a/Tests/Tests/SDImageCacheTests.m b/Tests/Tests/SDImageCacheTests.m index 4480aafb..f4f066b6 100644 --- a/Tests/Tests/SDImageCacheTests.m +++ b/Tests/Tests/SDImageCacheTests.m @@ -1,10 +1,10 @@ -// -// SDImageCacheTests.m -// SDWebImage Tests -// -// Created by Bogdan Poplauschi on 20/06/14. -// -// +/* + * This file is part of the SDWebImage package. + * (c) Olivier Poitrey + * + * 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 diff --git a/Tests/Tests/SDWebImageDownloaderTests.m b/Tests/Tests/SDWebImageDownloaderTests.m index 7fa5c5c8..f7b7641a 100644 --- a/Tests/Tests/SDWebImageDownloaderTests.m +++ b/Tests/Tests/SDWebImageDownloaderTests.m @@ -1,10 +1,11 @@ -// -// SDWebImageDownloaderTests.m -// SDWebImage Tests -// -// Created by Matt Galloway on 01/09/2014. -// -// +/* + * This file is part of the SDWebImage package. + * (c) Olivier Poitrey + * (c) Matt Galloway + * + * 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 diff --git a/Tests/Tests/SDWebImageManagerTests.m b/Tests/Tests/SDWebImageManagerTests.m index dc34d3a9..aeb00426 100644 --- a/Tests/Tests/SDWebImageManagerTests.m +++ b/Tests/Tests/SDWebImageManagerTests.m @@ -1,10 +1,10 @@ -// -// SDWebImageManagerTests.m -// SDWebImage Tests -// -// Created by Bogdan Poplauschi on 20/06/14. -// -// +/* + * This file is part of the SDWebImage package. + * (c) Olivier Poitrey + * + * 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 diff --git a/Tests/Tests/UIImageMultiFormatTests.m b/Tests/Tests/UIImageMultiFormatTests.m index 00b39549..310cfc7d 100644 --- a/Tests/Tests/UIImageMultiFormatTests.m +++ b/Tests/Tests/UIImageMultiFormatTests.m @@ -1,10 +1,10 @@ -// -// UIImageMultiFormatTests.m -// SDWebImage Tests -// -// Created by Bogdan Poplauschi on 18/07/14. -// -// +/* + * This file is part of the SDWebImage package. + * (c) Olivier Poitrey + * + * 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 diff --git a/WebImage/Info.plist b/WebImage/Info.plist index 9369da1a..ddbaa33b 100644 --- a/WebImage/Info.plist +++ b/WebImage/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 3.7.6 + 3.8.0 CFBundleSignature ???? CFBundleVersion diff --git a/WebImage/SDWebImage.h b/WebImage/SDWebImage.h index b95b911d..4ecf5bd2 100644 --- a/WebImage/SDWebImage.h +++ b/WebImage/SDWebImage.h @@ -1,10 +1,11 @@ -// -// WebImage.h -// WebImage -// -// Created by Florent Vilmart on 2015-03-14. -// Copyright (c) 2015 Dailymotion. All rights reserved. -// +/* + * This file is part of the SDWebImage package. + * (c) Olivier Poitrey + * (c) Florent Vilmart + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ #import