7

给出一些上下文:我正在尝试为身份验证错误实现一个全局错误处理程序(使用令牌身份验证,而不是基本的),它应该尝试重新进行身份验证,然后重复原始失败的请求(请参阅我之前的问题:AFNetworking:Handle全局错误并重复请求

当前的方法是为AFNetworkingOperationDidFinishNotification执行重新身份验证的观察者注册一个观察者,并且(如果身份验证成功)重复原始请求:

- (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?
            }
        ];
    }
}

但是,我偶然发现了一些关于请求操作完成块的问题:

  • 重复原始请求时,我显然希望执行其完成块。但是,AFHTTPRequestOperation不保留对传递的成功和失败块的引用(请参阅 参考资料setCompletionBlockWithSuccess:failure:),并且复制NSOperation'scompletionBlock可能不是一个好主意,因为AFURLConnectionOperation状态的文档:

    操作副本不包括completionBlock. completionBlock通常强烈地捕获对 的引用,也许令人惊讶的是,它在复制时self会指向原始操作。

  • 如果重新认证失败,我想调用原始请求的失败块。所以,再一次,我需要直接访问它。

我在这里错过了什么吗?关于替代方法的任何想法?我应该提交功能请求吗?

4

2 回答 2

1

我在Art.sy的投资组合应用程序中提出了这个问题。我最终的结论是创建一个 NSOperationQueue 子类,该子类具有在各种 AFNetworking HTTP 操作失败时创建副本的功能(并且在放弃之前每个 URL 最多执行 3 次。)

于 2012-10-27T13:55:23.407 回答
0

您是否尝试过以下操作?

// set success / failure block of original operation
[newOperation setCompletionBlock:[operation.completionBlock copy]];
[operation setCompletionBlock:nil];

请注意,如果您在原始完成/失败块中捕获 self(即访问任何 ivars),则在执行 newOperation 的完成块时您实际上访问的是原始操作实例。但这实际上是你想要的,对吧?

通知处理程序在操作的完成块之前执行。所以你应该将原始操作的完成块设置为nil,以防止它执行两次。

请注意,完成块在执行后设置为 nil(请参阅 AFURLConnectionOperation)。

在 authenticateWithCredentials 失败块中,您不应该做任何事情。原始操作在那个时候已经完成并且已经执行了它的失败块。

于 2012-10-28T10:42:20.733 回答