Adjust completion block implementation for RKPaginator to enable completion block to be invoked when used without a strong reference. fixes #1119 fixes #1093

This commit is contained in:
Blake Watters
2013-01-01 22:21:47 -05:00
parent 28887d3384
commit c08909761e
3 changed files with 43 additions and 19 deletions

View File

@@ -201,6 +201,20 @@ static NSString *RKStringDescribingURLResponseWithData(NSURLResponse *response,
}
}
- (void)setWillMapDeserializedResponseBlock:(id (^)(id))block
{
if (!block) {
_willMapDeserializedResponseBlock = nil;
} else {
__unsafe_unretained id weakSelf = self;
_willMapDeserializedResponseBlock = ^id (id deserializedResponse) {
id result = block(deserializedResponse);
[weakSelf setWillMapDeserializedResponseBlock:nil];
return result;
};
}
}
- (void)setCompletionBlockWithSuccess:(void (^)(RKObjectRequestOperation *operation, RKMappingResult *mappingResult))success
failure:(void (^)(RKObjectRequestOperation *operation, NSError *error))failure
{

View File

@@ -178,20 +178,21 @@ static NSUInteger RKPaginatorDefaultPerPage = 25;
// Add KVO to ensure notification of loaded state prior to execution of completion block
[self.objectRequestOperation addObserver:self forKeyPath:@"isFinished" options:0 context:nil];
__weak RKPaginator *weakSelf = self;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-retain-cycles"
[self.objectRequestOperation setWillMapDeserializedResponseBlock:^id(id deserializedResponseBody) {
NSError *error = nil;
RKMappingOperation *mappingOperation = [[RKMappingOperation alloc] initWithSourceObject:deserializedResponseBody destinationObject:weakSelf mapping:weakSelf.paginationMapping];
RKMappingOperation *mappingOperation = [[RKMappingOperation alloc] initWithSourceObject:deserializedResponseBody destinationObject:self mapping:self.paginationMapping];
BOOL success = [mappingOperation performMapping:&error];
if (!success) {
weakSelf.pageCount = 0;
weakSelf.currentPage = 0;
self.pageCount = 0;
self.currentPage = 0;
RKLogError(@"Paginator didn't map info to compute page count. Assuming no pages.");
} else if (weakSelf.perPage && [weakSelf hasObjectCount]) {
float objectCountFloat = weakSelf.objectCount;
weakSelf.pageCount = ceilf(objectCountFloat / weakSelf.perPage);
RKLogInfo(@"Paginator objectCount: %ld pageCount: %ld", (long)weakSelf.objectCount, (long)weakSelf.pageCount);
} else if (self.perPage && [self hasObjectCount]) {
float objectCountFloat = self.objectCount;
self.pageCount = ceilf(objectCountFloat / self.perPage);
RKLogInfo(@"Paginator objectCount: %ld pageCount: %ld", (long)self.objectCount, (long)self.pageCount);
} else {
RKLogError(@"Paginator perPage set is 0.");
}
@@ -199,14 +200,15 @@ static NSUInteger RKPaginatorDefaultPerPage = 25;
return deserializedResponseBody;
}];
[self.objectRequestOperation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
if (weakSelf.successBlock) {
weakSelf.successBlock(weakSelf, [mappingResult array], weakSelf.currentPage);
if (self.successBlock) {
self.successBlock(self, [mappingResult array], self.currentPage);
}
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
if (weakSelf.failureBlock) {
weakSelf.failureBlock(weakSelf, error);
if (self.failureBlock) {
self.failureBlock(self, error);
}
}];
#pragma clang diagnostic pop
if (self.operationQueue) {
[self.operationQueue addOperation:self.objectRequestOperation];

View File

@@ -220,9 +220,7 @@ static NSString * const RKPaginatorTestResourcePathPattern = @"/paginate?per_pag
} failure:nil];
[paginator loadPage:1];
[paginator waitUntilFinished];
dispatch_async(dispatch_get_main_queue(), ^{
expect(blockObjects).notTo.beNil();
});
expect(blockObjects).willNot.beNil();
}
- (void)testOnDidFailWithErrorBlockIsInvokedOnError
@@ -235,9 +233,19 @@ static NSString * const RKPaginatorTestResourcePathPattern = @"/paginate?per_pag
}];
[paginator loadPage:999];
[paginator waitUntilFinished];
dispatch_async(dispatch_get_main_queue(), ^{
expect(expectedError).notTo.beNil();
});
expect(expectedError).willNot.beNil();
}
- (void)testInvocationOfCompletionBlockWithoutWaiting
{
NSURLRequest *request = [NSURLRequest requestWithURL:self.paginationURL];
RKPaginator *paginator = [[RKPaginator alloc] initWithRequest:request paginationMapping:self.paginationMapping responseDescriptors:@[ self.responseDescriptor ]];
__block NSArray *blockObjects = nil;
[paginator setCompletionBlockWithSuccess:^(RKPaginator *paginator, NSArray *objects, NSUInteger page) {
blockObjects = objects;
} failure:nil];
[paginator loadPage:1];
expect(blockObjects).willNot.beNil();
}
- (void)testLoadingNextPageOfObjects