4

アプリケーションで AFNetworking を使用しており、進行状況 HUD に「タップしてキャンセル」機能を実装しようとしています。すべての HTTP 要求を管理するシングルトン クラスがあります。プログレス HUD がタップされた場合は、次のように呼び出します。

[[[HTTPRequestSingleton sharedClient] operationQueue] cancelAllOperations];

しかし、これは必要な操作を「キャンセル」しません。NSOperationQueue私はドキュメントを読んで、これに出くわしました:

操作オブジェクトをキャンセルすると、オブジェクトはキューにオブジェクトを残しますが、タスクをできるだけ早く中止する必要があることをオブジェクトに通知します。現在操作を実行している場合、これは、操作オブジェクトの作業コードがキャンセル状態を確認し、それがしていることを停止し、完成したとおりに自分自身をマークする必要があることを意味します。キューに掲載されていないがまだ実行されていない操作の場合、キューは引き続き操作オブジェクトの開始方法を呼び出して、キャンセルイベントを処理し、完成したとおりに自分自身をマークする必要があります。

そして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コールバックで変数を取得するためにやりたいことは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 に答える