Está llamando – ¿es una buena idea?

¿Generalmente es una buena idea llamar -[NSRunLoop runUntilDate:] ? Parece que funciona sin problemas, pero me pone nervioso decirle al ciclo de ejecución que se ejecute desde el bucle de ejecución.

Más información:

Tengo un proyecto en este momento que está trayendo datos de un service REST. Una pieza crítica de información que debe getse es el range de dates con datos válidos. Es un dato muy pequeño que solo se necesita get una vez, así que decidí que la mejor manera de manejarlo es hacer que la propiedad descargue los datos si la variable local es nil . Estoy usando ASIHTTPRequest y un ASINetworkQueue , así que todo es asíncrono de manera pnetworkingeterminada, y para que esto funcione, esta propiedad no puede volver hasta que los datos se hayan descargado y procesado. Aquí hay un resumen de mi código, los nombres de las variables se han cambiado para proteger a los inocentes:

 __block BOOL isWorking = YES; __block ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:/*actual URL*/] autorelease]; [request setCompletionBlock:^{ // set local variable isWorking = NO; }]; [request setFailedBlock:^{ // show alert to user isWorking = NO; }]; [queue addOperation:request]; while (isWorking) { [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; } 

Nuevamente, esto parece estar funcionando bien. ¿Hay problemas potenciales con el uso de este enfoque?

Debe asegurarse de no hacer esto desde cualquier método al que pueda invocar el ciclo de ejecución que está invocando, a less que el tree de llamadas superpuesto se vuelva a iniciar por completo.

El código Cocoa Touch UI no está documentado como reentrenante (de hecho, hay advertencias / sugerencias de Apple DTS que no lo es), por lo que si su manejador de datos de búsqueda puede llamarse de alguna manera mediante un método de interfaz de usuario (u otro método no -código de reinput que podría llamarse en el ciclo de ejecución de UI), no se recomienda llamar al ciclo de ejecución de UI desde el interior.

¿No es mejor mostrar algún tipo de spinner y descomponerlo en respuesta a los events de finalización asíncrona del código de networking? Me gusta:

 [self displayLoadingSpinner]; [request setCompletionBlock:^{ [self handleSuccess]; dispatch_async(dispatch_get_main_queue(), ^{ [self hideLoadingSpinner]; }]; }]; [request setFailedBlock:^{ [self handleFailure]; dispatch_async(dispatch_get_main_queue(), ^{ [self hideLoadingSpinner]; }]; }]; [queue addOperation:request]; 

Consideraría esto mejor que simular con el ciclo de ejecución. Pero podría ser que ya lo sepas y solo quieres saber qué inconvenientes exactos hay en la solución de runloop?


Si desea bloquear hasta que el valor esté listo, puede usar un semáforo:

 dispatch_semaphore_t sem = dispatch_semaphore_create(0); [request setCompletionBlock:^{ dispatch_semaphore_signal(sem); }]; [queue addOperation:request]; dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER); dispatch_release(sem);