2011-05-05 5 views
7

Me encontré con un bloqueo muy extraño con la aplicación de mi iPhone en desarrollo. Parecía que cada vez que le mostraba mi aplicación a un amigo se bloqueaba, pero de lo contrario no se colgaría. Después de haber sido en general desconcertado por el aspecto de la Ley de Murphy, he determinado el patrón de accidentes: el metro de la ciudad de Nueva York. Mi aplicación se bloquea constantemente después de usar el metro. He rastreado el problema hasta mi uso de Reachability. La aplicación se bloquea la próxima vez después de usarse en una situación sin red (sin incluir el modo avión). Estoy siguiendo las pautas de Apple y buscando una conexión con Reachability antes de hacer cualquier otra operación de red, pero he encontrado documentación contradictoria sobre cómo llamarla.La accesibilidad causa un bloqueo después de que no haya una situación de red: cómo usar correctamente la accesibilidad de forma asíncrona

Actualmente estoy haciendo algo como esto:

-(BOOL)reachable { 
    Reachability *r = [Reachability reachabilityWithHostName:@"www.stackoverflow.com"]; 
    NetworkStatus internetStatus = [r currentReachabilityStatus]; 
    if(internetStatus == NotReachable) { 
     return NO; 
    } 
    return YES; 

}

la que estoy llamando de forma sincronizada con un método llamado de viewDidAppear.

if ([self reachable]== YES) { 
     ... do network stuff ... 

que se basa en el código de Reachability Guide for iOS 4

Mi pregunta: ¿Hay un uso adecuado de Reachability que se hará cargo de este error y manejar la ausencia de una red 3G o Wifi? ¿Necesito generar otro hilo o hacer algo para eliminar una llamada síncrona?

Aquí, por cierto, está el registro de bloqueo que veo cuando se bloquea mi aplicación, lo que me lleva a pensar que se trata de un problema sincrónico/asincrónico.

 

Application Specific Information: 
(app name) failed to resume in time 

Elapsed total CPU time (seconds): 3.280 (user 1.770, system 1.510), 33% CPU 
Elapsed application CPU time (seconds): 0.040, 0% CPU 

Thread 0 name: Dispatch queue: com.apple.main-thread 
Thread 0: 
0 libsystem_kernel.dylib   0x30747fbc kevent + 24 
1 libsystem_info.dylib   0x30abec4e _mdns_search + 586 
2 libsystem_info.dylib   0x30abfb72 mdns_addrinfo + 370 
3 libsystem_info.dylib   0x30abfd68 search_addrinfo + 76 
4 libsystem_info.dylib   0x30ac1bcc si_addrinfo + 1080 
5 libsystem_info.dylib   0x30abd0b2 getaddrinfo + 78 
6 SystemConfiguration    0x311b4256 __SCNetworkReachabilityGetFlags + 962 
7 SystemConfiguration    0x311b4f1e SCNetworkReachabilityGetFlags + 98 

Respuesta

-1

He resuelto mi problema configurándolo para que sea asincrónico. Que llamo un método como este

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
NSTimer *timer = [NSTimer timerWithTimeInterval:0 target:self selector:@selector(loadData) userInfo:nil repeats:NO]; 
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode]; 
[pool release]; 

y el método denominado ve algo como esto

- (void)loadData { 
    // check for reachability first before starting data load 
    if ([self reachable]== NO) { 
     // display error message that there is no internet connection, e.g. 
     UIAlertView *errorAlert = [[UIAlertView alloc] initWithTitle:@"Connection Error" message:@"Cannot load data. There is no internet connection." delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Retry",nil]; 
     [errorAlert show]; 
     [errorAlert release]; 
    } else { 
     // do something to load data from internet ...  
    } 

} 

utilizando el mismo código accesible que el anterior.

Yo diría que siempre use Reachability de esta manera: el ejemplo que da Apple es incompleto. He tenido este código ejecutándose en una aplicación completa durante unos meses y ha sido muy estable.

EDIT: Este código ya no estables como de iOS 5 es - ahora a veces puede fallar debido a las "afirmaciones activos más allá del tiempo permitido". Apple ha actualizado su documentación y código de ejemplo desde que escribí esta pregunta, por lo que sugiero seguir el enlace en otra respuesta.

4

En el caso síncrono, es probable que el iOS Application Watchdog te mate. Eso es porque para hacer la verificación de accesibilidad, la funcionalidad SCNetworkReachability necesita hacer una búsqueda de DNS que puede tomar hasta 30 segundos. Si verifica la accesibilidad en el hilo principal (es decir, en viewDidAppear) bloquea el hilo principal durante un tiempo potencialmente prolongado, iOS piensa que su aplicación está colgada y que el perro guardián de la aplicación la elimina después de 20 segundos.

de Apple, incluso advierte sobre esto en el código de ejemplo Reacahbility:

Apple Reachability Sample Code README

sólo tiene que utilizar las notificaciones como en la aplicación de ejemplo de accesibilidad --- funciona bien y es bastante sencillo una vez que el patrón de diseño Grok NSNotificationCenter .

¡Buena suerte!

+0

Gracias - entonces si el hilo principal se matara, ¿sería coherente con lo que estaba viendo cuando lo estaba verificando sincrónicamente? (la aplicación bloquea la siguiente vez que se ejecuta después de la verificación sincrónica a reachabiity) –

Cuestiones relacionadas