2013-12-22 10 views
7

GoogleプレイスAPIを使用して検索バーにオートコンプリートを統合しています。ネットワーキングリクエストについては、AFNetworkingを使用しています。なぜAFHTTPRequestOperationがキャンセルされて成功ブロックにヒットするのですか?

一度に1つのリクエストしか実行しません。だから、毎回私は新しい文字を入力し、私は次の操作を行います

1 - 前回AFHTTPRequestOperationキャンセル:

[self.currentGlobalSearchListRequest cancel]; 
NSLog(@"%@ cancelled", self.currentGlobalSearchListRequest); 

2 - 新AFHTTPRequestOperationを起動します。コールバックはここ

self.currentGlobalSearchListRequest = [searchService getGlobalSearchListItemsForString:searchString inRegion:region delegate:self]; 
NSLog(@"%@ started", self.currentGlobalSearchListRequest); 

と呼ばれています要求が実行を終了したとき:

- (void)request:(PointSearchRequest *)request didLoadSearchListItems:(NSArray *)searchListItems { 
    NSAssert(request == self.currentGlobalSearchListRequest, @"!!!callback from a request that should be cancelled!!!"); 
    [self.delegate searchListLoader:self didLoadGlobalSearchList:searchListItems]; 
} 

時々私はアサートを打つ私はちょっと調べて、ほとんどの場合 エラーブロックNSURLErrorCancelledと呼ばれるエラーブロックが呼び出されることを発見しました。これは予想される動作ですが、成功ブロックが呼び出されることもあります。

このスタックトレースが私のコードで物事を正しい順序

2013-12-22 09:38:46.484 Point[63595:a0b] <PointSearchRequest: 0x18202b50> started 
2013-12-22 09:38:46.486 Point[63595:a0b] <PointSearchRequest: 0x18202b50> cancelled 
2013-12-22 09:38:46.487 Point[63595:a0b] <PointSearchRequest: 0x181a5dd0> started 
2013-12-22 09:38:46.496 Point[63595:a0b] *** Assertion failure in -[SearchListLoader request:didLoadSearchListItems:], /Users/aurelienporte/Documents/Developpement/Perso/iOS/Point/Point/Classes/Models/SearchListLoader.m:82 
(lldb) po request 
<PointSearchRequest: 0x18202b50> 

プラスに発生したことを私に告げる成功ブロックが呼び出されたとき、私はAFHTTPRequestOperationのプロパティisCancelledを見ていないが、それは(NO、私を与えます! ) 私はNSAssertを使用する代わりにテストを終了することができますが、問題の原因を突き止めたいと思います。

キャンセルが実際にリクエストをキャンセルしない同様の問題が発生しましたか?そして、失敗ブロックの代わりに成功ブロックが呼び出されますか?これはAFNetworkingチームに報告するための問題ですか?ありがとう!それは助けることができるならば、我々はすべて知っているよう

、リクエストが

+0

私はこれを期待しています。完了ハンドラを起動していない完了した操作をキャンセルすることはあいまいです。完了ハンドラを起動するか、取り消しを受け入れることができます。私は時間の100%起こってどちらかに数えません。 –

答えて

1

AFNetworkingCodeに見ると、参照AFURLConnectionOperation.m, line 461

- (void)cancel { 
    [self.lock lock]; 
    if (![self isFinished] && ![self isCancelled]) { 
     [super cancel]; 

     if ([self isExecuting]) { 
      [self performSelector:@selector(cancelConnection) onThread:[[self class] networkRequestThread] withObject:nil waitUntilDone:NO modes:[self.runLoopModes allObjects]]; 
     } 
    } 
    [self.lock unlock]; 
} 

あなたが見ている競合状態のための唯一の可能性は、操作が既に終了している場合([self isFinished])があるようです。 cancelと完了ブロックの間の間隔は非常に小さい(10ミリ秒)ことに注意してください。リクエストをキャンセルする前にisFinishedをチェックすることができますか?

+0

私はこれを見て、実際には、私のNSAssertが発生する状況で操作が完了しています。ありがとう。これは、 'isFinished'がYESに設定されてから、成功ブロックまたは失敗ブロックが呼び出されるまでの間に遅延があることを意味します。私は、これらの2つの「瞬間」は同じスレッドでは発生しないからだと思いますよね? –

+1

@AurelienPorteはい。 'NSOperation'はすぐに' completionBlock'を呼び出すべきですが、成功ブロックか失敗ブロックが呼び出される前に 'dispatch_async'が2つあります。すべての 'dispatch_async'は実行を少し延期します。これは、AFNetworkingがいくつかのディスパッチキューを使用し、実行が成功ブロックに達する前にすべてを通過しなければならないためです。 – Sulthan

0

(グーグルのオートコンプリートAPIが印象的です...)、高速おかしくしているあなたは、途中で糸をキャンセルもののときに、スレッド関数は、無行きます開始すると、メソッドが完了します。したがって、要求として。つまり、リクエストがNSOperationQueueにまだ残っている場合はキャンセルできますが、操作をサミットしてブロックがコピーされている限り、コールバックします。

コールバックを受け入れたくない場合は、コールバックでただちにリクエストがキャンセルされたかどうかを知ることができます。

お手数ですが、

+0

ありがとうございます。私は一般的なケースで同意します。そして、これはAFNetworkingライブラリ自体によって処理されるはずなので、私の失敗ブロックを呼び出す必要があります。 –

関連する問題