To give some context: I'm trying to implement a global error handler for authentication errors (using token authentication, not basic), which should try to re-authenticate and then repeat the original failed request (see my previous question: AFNetworking: Handle error globally and repeat request)
The current approach is to register an observer for the AFNetworkingOperationDidFinishNotification
which does the re-authentication and (if auth succeeded) repeats the original request:
- (void)operationDidFinish:(NSNotification *)notification
{
AFHTTPRequestOperation *operation = (AFHTTPRequestOperation *)[notification object];
if(![operation isKindOfClass:[AFHTTPRequestOperation class]]) {
return;
}
if(403 == [operation.response statusCode]) {
// try to re-authenticate and repeat the original request
[[UserManager sharedUserManager] authenticateWithCredentials...
success:^{
// repeat original request
// AFHTTPRequestOperation *newOperation = [operation copy]; // copies too much stuff, eg. response (although the docs suggest otherwise)
AFHTTPRequestOperation *newOperation = [[AFHTTPRequestOperation alloc] initWithRequest:operation.request];
// PROBLEM 1: newOperation has no completion blocks. How to use the original success/failure blocks here?
[self enqueueHTTPRequestOperation:newOperation];
}
failure:^(NSError *error) {
// PROBLEM 2: How to invoke failure block of original operation?
}
];
}
}
However, I stumbled upon some issues regarding completion blocks of request operations:
When repeating the original request, I obviously want its completion blocks to be executed. However, AFHTTPRequestOperation
does not retain references to the passed success and failure blocks (see setCompletionBlockWithSuccess:failure:
) and copying NSOperation
's completionBlock
is probably not a good idea, as the documentation for AFURLConnectionOperation
states:
Operation copies do not include
completionBlock
.completionBlock
often strongly captures a reference toself
, which, perhaps surprisingly, would otherwise point to the original operation when copied.
In case the re-authentication fails, I want to call the original request's failure block. So, again, I'd need direct access to this.
Am I missing something here? Any ideas for alternative approaches? Should I file a feature request?
I've come up with this problem in Art.sy's portfolio app. My eventual conclusion was to create a NSOperationQueue subclass which had functions to create copies of various AFNetworking HTTP Operations once they failed (and to do this up to three times per URL before giving up.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With