如何使用AFNetworking立即强制取消NSOperation?

时间:2012-09-11 02:12:53

标签: objective-c cocoa-touch nsoperation afnetworking

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

[[[HTTPRequestSingleton sharedClient] operationQueue] cancelAllOperations];

但这并不像我需要的那样“取消”操作。我读了NSOperationQueue docs并发现了这个:

  

取消操作对象会将对象留在队列中,但会通知对象它应该尽快中止其任务。对于当前正在执行的操作,这意味着操作对象的工作代码必须检查取消状态,停止它正在执行的操作,并将自己标记为已完成。对于排队但尚未执行的操作,队列仍必须调用操作对象的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

}];

2 个答案:

答案 0 :(得分:9)

经过整整一天的AFNetworking源代码挖掘后,事实证明我的操作没有取消的原因与操作本身无关,而是因为我一直在错误地开始操作。我一直在使用

[NSOperation start];

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

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

将其添加到队列中可以正确取消它,而无需检查isCancelled属性。

答案 1 :(得分:3)

  

completionBlock

     

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

     
      
  • (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