diff --git a/AFIncrementalStore/AFIncrementalStore.h b/AFIncrementalStore/AFIncrementalStore.h index 7ea486b..b8ba2db 100644 --- a/AFIncrementalStore/AFIncrementalStore.h +++ b/AFIncrementalStore/AFIncrementalStore.h @@ -288,6 +288,10 @@ - (BOOL)authenticateRequest:(NSURLRequest *)request fromResponseObject:(id)responseObject; +- (BOOL)shouldRetryRequest:(NSURLRequest *)request forUpdatedObject:(NSManagedObject *)updatedObject; + +- (void)updateRetryMetadataForRequest:(NSURLRequest *)request forUpdateObject:(NSManagedObject *)updatedObject; + @end ///---------------- diff --git a/AFIncrementalStore/AFIncrementalStore.m b/AFIncrementalStore/AFIncrementalStore.m index f6aabe3..229bf7a 100644 --- a/AFIncrementalStore/AFIncrementalStore.m +++ b/AFIncrementalStore/AFIncrementalStore.m @@ -507,6 +507,7 @@ - (id)executeSaveChangesRequest:(NSSaveChangesRequest *)saveChangesRequest withContext:(NSManagedObjectContext *)context error:(NSError *__autoreleasing *)error { + dispatch_group_t group = dispatch_group_create(); NSMutableArray *mutableOperations = [NSMutableArray array]; NSManagedObjectContext *backingContext = [self backingManagedObjectContext]; @@ -602,8 +603,9 @@ - (id)executeSaveChangesRequest:(NSSaveChangesRequest *)saveChangesRequest if ([self.HTTPClient respondsToSelector:@selector(requestForUpdatedObject:)]) { for (NSManagedObject *updatedObject in [saveChangesRequest updatedObjects]) { + NSManagedObjectContext *backingContext = [self backingManagedObjectContext]; NSManagedObjectID *backingObjectID = [self objectIDForBackingObjectForEntity:[updatedObject entity] withResourceIdentifier:AFResourceIdentifierFromReferenceObject([self referenceObjectForObjectID:updatedObject.objectID])]; - + NSURLRequest *request = [self.HTTPClient requestForUpdatedObject:updatedObject]; if (!request) { [backingContext performBlockAndWait:^{ @@ -611,40 +613,14 @@ - (id)executeSaveChangesRequest:(NSSaveChangesRequest *)saveChangesRequest [self updateBackingObject:backingObject withAttributeAndRelationshipValuesFromManagedObject:updatedObject]; [backingContext save:nil]; }]; - continue; + return nil; } - - AFHTTPRequestOperation *operation = [self.HTTPClient HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) { - BOOL isAuthenticated = YES; - if ([self.HTTPClient respondsToSelector:@selector(authenticateRequest:fromResponseObject:)]) { - isAuthenticated = [self.HTTPClient authenticateRequest:request fromResponseObject:responseObject]; - } - if (isAuthenticated) { - id representationOrArrayOfRepresentations = [self.HTTPClient representationOrArrayOfRepresentationsOfEntity:[updatedObject entity] fromResponseObject:responseObject]; - if ([representationOrArrayOfRepresentations isKindOfClass:[NSDictionary class]]) { - NSDictionary *representation = (NSDictionary *)representationOrArrayOfRepresentations; - [updatedObject setValuesForKeysWithDictionary:[self.HTTPClient attributesForRepresentation:representation ofEntity:updatedObject.entity fromResponse:operation.response]]; - - [backingContext performBlockAndWait:^{ - NSManagedObject *backingObject = [backingContext existingObjectWithID:backingObjectID error:nil]; - [self updateBackingObject:backingObject withAttributeAndRelationshipValuesFromManagedObject:updatedObject]; - [backingContext save:nil]; - }]; - [context refreshObject:updatedObject mergeChanges:YES]; - } - } - else { - NSLog(@"Update Error: authentication failed"); - [context refreshObject:updatedObject mergeChanges:NO]; - } - } failure:^(AFHTTPRequestOperation *operation, NSError *error) { - NSLog(@"Update Error: %@", error); - [context refreshObject:updatedObject mergeChanges:NO]; - }]; - operation.completionGroup = group; - - [mutableOperations addObject:operation]; + AFHTTPRequestOperation *operation = [self operationForRequest:request updatedObject:updatedObject inManagedObjectContext:context]; + if (operation) { + operation.completionGroup = group; + [mutableOperations addObject:operation]; + } } } @@ -695,6 +671,60 @@ - (id)executeSaveChangesRequest:(NSSaveChangesRequest *)saveChangesRequest return [NSArray array]; } +- (AFHTTPRequestOperation *)operationForRequest:(NSURLRequest *)request updatedObject:(NSManagedObject *)updatedObject inManagedObjectContext:(NSManagedObjectContext *)context +{ + NSManagedObjectContext *backingContext = [self backingManagedObjectContext]; + NSManagedObjectID *backingObjectID = [self objectIDForBackingObjectForEntity:[updatedObject entity] withResourceIdentifier:AFResourceIdentifierFromReferenceObject([self referenceObjectForObjectID:updatedObject.objectID])]; + + AFHTTPRequestOperation *operation = [self.HTTPClient HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) { + BOOL shouldRetry = [updatedObject.entity.name isEqualToString:@"SurveyQuestion"] && [self.HTTPClient shouldRetryRequest:request forUpdatedObject:updatedObject]; + + BOOL isAuthenticated = YES; + if ([self.HTTPClient respondsToSelector:@selector(authenticateRequest:fromResponseObject:)]) { + isAuthenticated = [self.HTTPClient authenticateRequest:request fromResponseObject:responseObject]; + } + if (isAuthenticated) { + id representationOrArrayOfRepresentations = [self.HTTPClient representationOrArrayOfRepresentationsOfEntity:[updatedObject entity] fromResponseObject:responseObject]; + if ([representationOrArrayOfRepresentations isKindOfClass:[NSDictionary class]]) { + NSDictionary *representation = (NSDictionary *)representationOrArrayOfRepresentations; + [updatedObject setValuesForKeysWithDictionary:[self.HTTPClient attributesForRepresentation:representation ofEntity:updatedObject.entity fromResponse:operation.response]]; + + [backingContext performBlockAndWait:^{ + NSManagedObject *backingObject = [backingContext existingObjectWithID:backingObjectID error:nil]; + [self updateBackingObject:backingObject withAttributeAndRelationshipValuesFromManagedObject:updatedObject]; + [backingContext save:nil]; + }]; + + [context refreshObject:updatedObject mergeChanges:YES]; + } + } + else { + if (shouldRetry) { + [self.HTTPClient updateRetryMetadataForRequest:request forUpdateObject:updatedObject]; + AFHTTPRequestOperation *operation = [self operationForRequest:request updatedObject:updatedObject inManagedObjectContext:context]; + [operation start]; + } + else { + [context refreshObject:updatedObject mergeChanges:NO]; + } + NSLog(@"Update Error: authentication failed"); + } + } failure:^(AFHTTPRequestOperation *operation, NSError *error) { + BOOL shouldRetry = [updatedObject.entity.name isEqualToString:@"SurveyQuestion"] && [self.HTTPClient shouldRetryRequest:request forUpdatedObject:updatedObject]; + NSLog(@"Update Error: %@", error); + if (shouldRetry) { + [self.HTTPClient updateRetryMetadataForRequest:request forUpdateObject:updatedObject]; + AFHTTPRequestOperation *operation = [self operationForRequest:request updatedObject:updatedObject inManagedObjectContext:context]; + [operation start]; + } + else { + [context refreshObject:updatedObject mergeChanges:NO]; + } + }]; + + return operation; +} + #pragma mark - NSIncrementalStore - (BOOL)loadMetadata:(NSError *__autoreleasing *)error {