Explorar o código

Critical bug fixes for AFImageDownloader (tests coming soon)

Kevin Harwood %!s(int64=10) %!d(string=hai) anos
pai
achega
c54bf45980

+ 39 - 0
Tests/Tests/AFImageDownloaderTests.m

@@ -0,0 +1,39 @@
+//
+//  AFImageDownloaderTests.m
+//  AFNetworking Tests
+//
+//  Created by Kevin Harwood on 10/1/15.
+//  Copyright © 2015 AFNetworking. All rights reserved.
+//
+
+#import <XCTest/XCTest.h>
+
+@interface AFImageDownloaderTests : XCTestCase
+
+@end
+
+@implementation AFImageDownloaderTests
+
+- (void)setUp {
+    [super setUp];
+    // Put setup code here. This method is called before the invocation of each test method in the class.
+}
+
+- (void)tearDown {
+    // Put teardown code here. This method is called after the invocation of each test method in the class.
+    [super tearDown];
+}
+
+- (void)testExample {
+    // This is an example of a functional test case.
+    // Use XCTAssert and related functions to verify your tests produce the correct results.
+}
+
+- (void)testPerformanceExample {
+    // This is an example of a performance test case.
+    [self measureBlock:^{
+        // Put the code you want to measure the time of here.
+    }];
+}
+
+@end

+ 7 - 0
UIKit+AFNetworking/AFImageDownloader.h

@@ -74,6 +74,13 @@ typedef NS_ENUM(NSInteger, AFImageDownloadPrioritization) {
  */
 + (instancetype)defaultInstance;
 
+/**
+ Creates a default `NSURLCache` with common usage parameter values.
+
+ @returns The default `NSURLCache` instance.
+ */
++ (NSURLCache *)defaultURLCache;
+
 /**
  Default initializer
 

+ 49 - 31
UIKit+AFNetworking/AFImageDownloader.m

@@ -21,7 +21,7 @@
 
 #import <TargetConditionals.h>
 
-#if TARGET_OS_IOS || TARGET_OS_TV 
+#if TARGET_OS_IOS || TARGET_OS_TV
 
 #import "AFImageDownloader.h"
 #import "AFHTTPSessionManager.h"
@@ -35,8 +35,8 @@
 @implementation AFImageDownloaderResponseHandler
 
 - (instancetype)initWithUUID:(NSUUID *)uuid
-                    success:(nullable void (^)(NSURLRequest *request, NSHTTPURLResponse * _Nullable response, UIImage *responseObject))success
-                    failure:(nullable void (^)(NSURLRequest *request, NSHTTPURLResponse * _Nullable response, NSError *error))failure {
+                     success:(nullable void (^)(NSURLRequest *request, NSHTTPURLResponse * _Nullable response, UIImage *responseObject))success
+                     failure:(nullable void (^)(NSURLRequest *request, NSHTTPURLResponse * _Nullable response, NSError *error))failure {
     if (self = [self init]) {
         self.uuid = uuid;
         self.successBlock = success;
@@ -45,6 +45,9 @@
     return self;
 }
 
+- (NSString *)description {
+    return [NSString stringWithFormat: @"<AFImageDownloaderResponseHandler>UUID: %@", [self.uuid UUIDString]];
+}
 
 @end
 
@@ -52,6 +55,7 @@
 @property (nonatomic, strong) NSString *identifier;
 @property (nonatomic, strong) NSURLSessionDataTask *task;
 @property (nonatomic, strong) NSMutableArray <AFImageDownloaderResponseHandler*> *responseHandlers;
+
 @end
 
 @implementation AFImageDownloaderMergedTask
@@ -137,9 +141,9 @@
 }
 
 - (instancetype)initWithSessionManager:(AFHTTPSessionManager *)sessionManager
-               downloadPrioritization:(AFImageDownloadPrioritization)downloadPrioritization
-               maximumActiveDownloads:(NSInteger)maximumActiveDownloads
-                           imageCache:(id <AFImageRequestCache>)imageCache {
+                downloadPrioritization:(AFImageDownloadPrioritization)downloadPrioritization
+                maximumActiveDownloads:(NSInteger)maximumActiveDownloads
+                            imageCache:(id <AFImageRequestCache>)imageCache {
     if (self = [super init]) {
         self.sessionManager = sessionManager;
 
@@ -174,17 +178,18 @@
 - (nullable AFImageDownloadReceipt *)downloadImageForURLRequest:(NSURLRequest *)request
                                                         success:(nullable void (^)(NSURLRequest *request, NSHTTPURLResponse  * _Nullable response, UIImage *responseObject))success
                                                         failure:(nullable void (^)(NSURLRequest *request, NSHTTPURLResponse * _Nullable response, NSError *error))failure; {
-
-    __block AFImageDownloadReceipt *downloadReceipt = nil;
+    NSUUID *callerUUID = [NSUUID UUID];
+    __block NSURLSessionDataTask *task = nil;
     dispatch_sync(self.synchronizationQueue, ^{
         NSString *identifier = request.URL.absoluteString;
-        NSUUID *callerUUID = [NSUUID UUID];
 
         // 1) Append the success and failure blocks to a pre-existing request if it already exists
         AFImageDownloaderMergedTask *existingMergedTask = self.mergedTasks[identifier];
         if (existingMergedTask != nil) {
             AFImageDownloaderResponseHandler *handler = [[AFImageDownloaderResponseHandler alloc] initWithUUID:callerUUID success:success failure:failure];
             [existingMergedTask addResponseHandler:handler];
+            task = existingMergedTask.task;
+            return;
         }
 
         // 2) Attempt to load the image from the image cache if the cache policy allows it
@@ -214,26 +219,37 @@
                        GET:request.URL.absoluteString
                        parameters:nil
                        success:^(NSURLSessionDataTask * _Nonnull task, id  _Nonnull responseObject) {
-                           __strong typeof(weakSelf) strongSelf = weakSelf;
-                           AFImageDownloaderMergedTask *mergedTask = [strongSelf safelyRemoveMergedTaskWithIdentifier:identifier];
-                           for (AFImageDownloaderResponseHandler *handler in mergedTask.responseHandlers) {
-                               dispatch_async(dispatch_get_main_queue(), ^{
-                                   handler.successBlock(task.originalRequest, (NSHTTPURLResponse*)task.response, responseObject);
-                               });
-                           }
-                           [strongSelf safelyDecrementActiveTaskCount];
-                           [strongSelf safelyStartNextTaskIfNecessary];
+                           dispatch_async(self.responseQueue, ^{
+                               __strong typeof(weakSelf) strongSelf = weakSelf;
+                               AFImageDownloaderMergedTask *mergedTask = [strongSelf safelyRemoveMergedTaskWithIdentifier:identifier];
+
+                               [strongSelf.imageCache addImage:responseObject forRequest:task.originalRequest withAdditionalIdentifier:nil];
+
+                               for (AFImageDownloaderResponseHandler *handler in mergedTask.responseHandlers) {
+                                   if (handler.successBlock) {
+                                       dispatch_async(dispatch_get_main_queue(), ^{
+                                           handler.successBlock(task.originalRequest, (NSHTTPURLResponse*)task.response, responseObject);
+                                       });
+                                   }
+                               }
+                               [strongSelf safelyDecrementActiveTaskCount];
+                               [strongSelf safelyStartNextTaskIfNecessary];
+                           });
                        }
                        failure:^(NSURLSessionDataTask * _Nonnull task, NSError * _Nonnull error) {
-                           __strong typeof(weakSelf) strongSelf = weakSelf;
-                           AFImageDownloaderMergedTask *mergedTask = [strongSelf safelyRemoveMergedTaskWithIdentifier:identifier];
-                           for (AFImageDownloaderResponseHandler *handler in mergedTask.responseHandlers) {
-                               dispatch_async(dispatch_get_main_queue(), ^{
-                                   handler.failureBlock(task.originalRequest, (NSHTTPURLResponse*)task.response, error);
-                               });
-                           }
-                           [strongSelf safelyDecrementActiveTaskCount];
-                           [strongSelf safelyStartNextTaskIfNecessary];
+                           dispatch_async(self.responseQueue, ^{
+                               __strong typeof(weakSelf) strongSelf = weakSelf;
+                               AFImageDownloaderMergedTask *mergedTask = [strongSelf safelyRemoveMergedTaskWithIdentifier:identifier];
+                               for (AFImageDownloaderResponseHandler *handler in mergedTask.responseHandlers) {
+                                   if (handler.failureBlock) {
+                                       dispatch_async(dispatch_get_main_queue(), ^{
+                                           handler.failureBlock(task.originalRequest, (NSHTTPURLResponse*)task.response, error);
+                                       });
+                                   }
+                               }
+                               [strongSelf safelyDecrementActiveTaskCount];
+                               [strongSelf safelyStartNextTaskIfNecessary];
+                           });
                        }];
         [createdTask suspend];
 
@@ -254,11 +270,13 @@
             [self enqueueMergedTask:mergedTask];
         }
 
-        // 6) Create the receipt
-        downloadReceipt = [[AFImageDownloadReceipt alloc] initWithReceiptID:callerUUID task:createdTask];
+        task = mergedTask.task;
     });
-
-    return downloadReceipt;
+    if (task) {
+        return [[AFImageDownloadReceipt alloc] initWithReceiptID:callerUUID task:task];
+    } else {
+        return nil;
+    }
 }
 
 - (void)cancelTaskForImageDownloadReceipt:(AFImageDownloadReceipt *)imageDownloadReceipt {