¿Por qué cancelar AFHTTPRequestOperation a veces golpea el bloque de éxito?

Estoy integrando autocomplete en una barra de búsqueda a través de la API de Google Places. Y para las requestes de networking, uso AFNetworking.

Quiero tener una sola request ejecutándose a la vez. Cada vez que escribo una nueva letra, hago lo siguiente:

1 – Cancele la anterior AFHTTPRequestOperation:

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

2 – Comienza una nueva AFHTTPRequestOperation:

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

Aquí está la callback llamada cuando la request ha terminado de ejecutarse:

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

A veces golpé la afirmación, así que investigé un poco y descubrí que la mayoría de las veces el bloque de falla se llama con un código de error NSURLErrorCancelled que es el comportamiento esperado, pero a veces, se llama al bloque de éxito.

Este rastreo de stack me dice que las cosas en mi código ocurrieron en el order correcto

 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> 

Además, isCancelled la propiedad está isCancelled en AFHTTPRequestOperation cuando se llama bloque de éxito, pero NO me da (!!!). Sé que podría terminar probando en lugar de usar NSAssert, pero me gustaría encontrar el origen del problema.

¿Alguna vez ha encontrado problemas similares en los que cancelar no cancela la request? ¿Y luego se llama al bloque de éxito en lugar del bloque de falla? ¿Es un problema informar al equipo de AFNetworking? ¡Gracias!

Si puede ayudar, las requestes se vuelven locas (el autocompletado de Google aPI es impresionante …)

Al mirar AFNetworkingCode , vea AFURLConnectionOperation.m, línea 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]; } 

Parece que la única posibilidad para la condición de carrera que está viendo es el caso cuando la operación ya ha finalizado ( [self isFinished] ). Tenga en count que el intervalo entre su bloque de cancel y finalización es muy pequeño (10 ms). ¿Tal vez podría comprobar que está isFinished antes de intentar cancelar la request?

Como todos sabemos, una function de subprocess no funcionará aunque cancele el subprocess en la mitad del path, cuando comience, completará el método. Así como la request. Es decir, si la request todavía está en NSOperationQueue, puede cancelarla, pero mientras cumbre la operación y el bloque se copie, devolverá la llamada.

Si no desea aceptar la callback, puede volver a llamar para indicar si la request se canceló.

Espero que te ayude.