4

我在我的应用程序中使用 AFNetworking,并尝试在我的进度 HUD 中实现“点击取消”功能。我有一个管理所有 HTTP 请求的单例类。如果点击进度HUD,我会调用:

[[[HTTPRequestSingleton sharedClient] operationQueue] cancelAllOperations];

但这不会像我需要的那样“取消”操作。我阅读了NSOperationQueue文档并遇到了这个:

取消操作对象会使对象留在队列中,但会通知对象它应该尽快中止其任务。对于当前正在执行的操作,这意味着操作对象的工作代码必须检查取消状态,停止正在执行的操作,并将自身标记为已完成。对于已排队但尚未执行的操作,队列仍必须调用操作对象的 start 方法,以便它可以处理取消事件并将自己标记为已完成。

关于cancelAllOperations方法:

此方法向队列中当前的所有操作发送取消消息。排队的操作在开始执行之前被取消。如果一个操作已经在执行,则由该操作来识别取消并停止它正在执行的操作。

我的问题似乎特别涉及已经执行的操作,我想立即取消。使用 AFNetworking,我如何提醒操作它应该取消并丢弃有关请求的所有信息?

用于操作的代码

AFJSONRequestOperation *loginOperation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {

    //operation was successful

    if (loginOperation.isCancelled)
    {
        //can't do this. variable 'loginOperation' is uninitialized when captured by block      
    }

} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {

    //operation failed

}];
4

2 回答 2

9

经过一上午的 AFNetworking 源代码挖掘后,我发现我的操作没有取消的原因与操作本身无关,而是因为我一直在错误地启动操作。我一直在使用

[NSOperation start];

当我应该将它添加到我HTTPRequestSingleton的操作队列时:

[[[HTTPRequestSingleton sharedClient] operationQueue] addOperation:NSOperation];

将它添加到队列允许它被正确取消而无需检查isCancelled属性。

于 2012-09-11T15:44:21.603 回答
3

完成块

当操作的主要任务完成时返回要执行的块。

  • (void (^)(void))completionBlock 返回值 操作的主要任务完成后要执行的块。这个块没有参数,也没有返回值。

讨论 当 isFinished 方法返回的值变为 YES 时,就会执行你提供的完成块。因此,该块由操作对象在操作的主要任务 完成或取消后执行。

检查操作isCancelled属性以了解调用回调的原因。


查看初始化代码:

+ (AFJSONRequestOperation *)JSONRequestOperationWithRequest:(NSURLRequest *)urlRequest
                                                    success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, id JSON))success 
                                                    failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON))failure
{
    AFJSONRequestOperation *requestOperation = [[[self alloc] initWithRequest:urlRequest] autorelease];
    [requestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
        if (success) {
            success(operation.request, operation.response, responseObject);
        }
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        if (failure) {
            failure(operation.request, operation.response, error, [(AFJSONRequestOperation *)operation responseJSON]);
        }
    }];
    
    return requestOperation;
}

您想要operation在回调中获取 var 是setCompletionBlockWithSuccess在初始化之后 使用,JSONRequestOperationWithRequest:success:failure:这有点矫枉过正,更好的方法是复制代码并使用

    AFJSONRequestOperation *requestOperation = [[[self alloc] initWithRequest:urlRequest] autorelease];
    [requestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {

    // ... here you can check `isCancelled` flag
于 2012-09-11T03:07:15.863 回答