Skip to content

Commit

Permalink
DFImageManager now guarantees that completion block will always be ca…
Browse files Browse the repository at this point in the history
…lled (even if the request was cancelled)
  • Loading branch information
kean committed Mar 18, 2015
1 parent 5d04321 commit 6cfc589
Show file tree
Hide file tree
Showing 7 changed files with 35 additions and 4 deletions.
1 change: 0 additions & 1 deletion DFImageManager/Source/Core/Managing/DFImageManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@

@class DFImageManagerConfiguration;


/*! The DFImageManager and the related classes provides an implementation of the DFImageManaging protocol. The role of the DFImageManager is to manage the execution of image requests by delegating the actual job to a classes, implementing DFImageFetching, DFImageCaching, and DFImageProcessing protocols.
@note Completion Block
Expand Down
5 changes: 5 additions & 0 deletions DFImageManager/Source/Core/Managing/DFImageManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,11 @@ - (void)_cancelRequestWithHandler:(_DFImageHandler *)handler {
_DFImageManagerTask *task = handler.task;
if ([task.handlers containsObject:handler]) {
[task removeHandler:handler];
if (handler.completionHandler) {
dispatch_async(dispatch_get_main_queue(), ^{
handler.completionHandler(nil, @{ DFImageInfoErrorKey: [NSError errorWithDomain:DFImageManagerErrorDomain code:DFImageManagerErrorCancelled userInfo:nil] });
});
}
if (task.handlers.count == 0) {
[task cancel];
[self _removeTask:task];
Expand Down
8 changes: 8 additions & 0 deletions DFImageManager/Source/Core/Support/DFImageManagerDefines.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,11 @@ typedef NS_ENUM(NSInteger, DFImageRequestPriority) {
/*! Progress handler, called on a main thread.
*/
typedef void (^DFImageRequestProgressHandler)(double progress);

/*! The error domain for DFImageManager.
*/
extern NSString *const DFImageManagerErrorDomain;

/*! Returned when an image request is cancelled.
*/
static const NSInteger DFImageManagerErrorCancelled = -1;
3 changes: 2 additions & 1 deletion DFImageManager/Source/Core/Support/DFImageManagerDefines.m
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,6 @@
NSString *const DFImageInfoRequestIDKey = @"DFImageInfoRequestIDKey";
NSString *const DFImageInfoErrorKey = @"DFImageInfoErrorKey";


CGSize const DFImageMaximumSize = { FLT_MAX, FLT_MAX };

NSString *const DFImageManagerErrorDomain = @"DFImageManagerErrorDomain";
2 changes: 1 addition & 1 deletion DFImageManager/Source/Core/Support/DFImageRequestID.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
*/
@interface DFImageRequestID : NSObject <NSCopying>

/*! Advices the image manager that the request should be cancelled.
/*! Advices the image manager that the request should be cancelled. The completion block will be called with error value of { DFImageManagerErrorDomain, DFImageManagerErrorCancelled }
*/
- (void)cancel;

Expand Down
4 changes: 3 additions & 1 deletion DFImageManager/Source/UI/UIImageView+DFImageManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@ - (void)df_setImageWithResource:(id)resource targetSize:(CGSize)targetSize conte
UIImageView *__weak weakSelf = self;
DFImageRequest *request = [DFImageRequest requestWithResource:resource targetSize:targetSize contentMode:contentMode options:options];
[[DFImageManager sharedManager] requestImageForRequest:request completion:^(UIImage *image, NSDictionary *info) {
weakSelf.image = image;
if (image) {
weakSelf.image = image;
}
}];
}

Expand Down
16 changes: 16 additions & 0 deletions DFImageManager/Tests/Tests/TDFImageManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,21 @@ - (void)testThatCancelsFetchOperationWithTwoHandlers {
[self waitForExpectationsWithTimeout:3.0 handler:nil];
}

- (void)testThatCompletionHandlerForCancelledRequestIsCalled {
_fetcher.queue.suspended = YES;

XCTestExpectation *expectation = [self expectationWithDescription:@""];
DFImageRequestID *requestID = [_manager requestImageForResource:[TDFMockResource resourceWithID:@"ID01"] completion:^(UIImage *image, NSDictionary *info) {
NSError *error = info[DFImageInfoErrorKey];
XCTAssertNotNil(error);
XCTAssertTrue([error.domain isEqualToString:DFImageManagerErrorDomain]);
XCTAssertEqual(error.code, DFImageManagerErrorCancelled);
[expectation fulfill];
}];
[requestID cancel];
[self waitForExpectationsWithTimeout:3.0 handler:nil];
}

#pragma mark - Operation Reuse

- (void)testThatOperationsAreReused {
Expand Down Expand Up @@ -325,6 +340,7 @@ - (void)testThatPriorityIsChanged {
XCTAssertEqual(operation.queuePriority, (NSOperationQueuePriority)DFImageRequestPriorityVeryLow);
[expectation fulfill];
}];
[NSThread sleepForTimeInterval:0.05]; // Wait till operation is created
[requestID setPriority:DFImageRequestPriorityVeryLow];

_fetcher.queue.suspended = NO;
Expand Down

0 comments on commit 6cfc589

Please sign in to comment.