2012-01-24 16 views
11

Tengo un UITableView que proviene de un canal RSS externo.Animate Spinner al cargar la nueva página

Cuando selecciona una fila usa navigationController y se desliza desde la derecha, el problema es que la fuente RSS contiene imágenes, por lo tanto, puede llevar unos segundos cargar y sin ninguna indicación de lo que está pasando puede confundirse para una falla de la aplicación.

Decidí agregar una ruleta para que sepas que la nueva página se está cargando.

Aquí está mi código:

RootViewController.m

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 
NSLog(@"Loading New Page"); 

[tableView deselectRowAtIndexPath:indexPath animated:YES]; 
DetailsViewController *detailViewController = [[DetailsViewController alloc] initWithNibName:@"DetailsViewController" bundle:nil]; 
detailViewController.item = [rssItems objectAtIndex:floor(indexPath.row/2)]; 
[self.navigationController pushViewController:detailViewController animated:YES]; 
[detailViewController release]; 

UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; 
spinner.center = CGPointMake(160, 240); 
[self.view addSubview:spinner]; 
[spinner startAnimating]; 
[spinner release]; 

} 

DetailsViewController.m

- (void)viewDidLoad { 
    [super viewDidLoad]; 

     NSString *imgURL = [item objectForKey:@"image"]; 
     NSData *mydata = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:imgURL]]; 
     item_photo.image = [[UIImage alloc] initWithData:mydata]; 

    item_title.text = [item objectForKey:@"title"]; 
    item_date.text = [NSString stringWithFormat:@"Date: %@",[item objectForKey:@"date"]]; 
    item_time.text = [NSString stringWithFormat:@"Time: %@",[item objectForKey:@"time"]]; 
    item_cost.text = [NSString stringWithFormat:@"Cost: £%@",[item objectForKey:@"cost"]]; 
    item_info.text = [item objectForKey:@"description"]; 
    self.navigationItem.title = @"Event Type"; 
} 

Hay dos problemas con este código.

  1. El Spinner no se activa hasta que se carga la nueva página.
  2. El Spinner no se desactiva una vez cargado.

Si alguien pudiera ayudarme con este problema, estaría realmente agradecido.

+0

Creo que todavía se está perdiendo el código donde a continuación, ver indicador de actividad se detiene/eliminado. Además: ¿cómo estás cargando las imágenes? Si está utilizando un método de bloqueo (es decir, uno que no se ejecuta en un hilo de fondo), todo su ciclo principal estará bloqueado, lo que significa: sin interacción del usuario, sin animación, etc. (lo que explicaría este comportamiento). Si este es el caso, realmente debería cambiar a la carga asíncrona. –

+0

@TriPhoenix ¿Cómo sabes si es un método de bloqueo o no? He agregado el código en DetailsViewController.m –

+0

Puede ver cómo funciona la función: las funciones de bloqueo devolverán el valor de inmediato, en este caso 'initWithContentsOfURL' habrá puesto los datos en su' NSData' para que el funciton no pueda devolverlos antes de haber devuelto esta información Las solicitudes asincrónicas son más complejas en el sentido de que usted inicia la solicitud y no se le devolverá el resultado, sino que la solicitud llamará a una función de devolución de llamada en su código cuando finalice. Hay algunos marcos como ASIHTTPRequest que hacen esto más fácil o puede usar NSURLConnection y hacerlo por su cuenta. –

Respuesta

23

Está añadiendo la vista indicador de actividad a la vista del controlador que está empujando el controlador de la vista de detalle, por lo que no se ve todos modos

trate de mover el segundo grupo de código al método viewDidLoad de DetailsViewController, se puede llamar a stopAnimating en el indicador de actividad cuando haya terminado de cargar. Para obtener una referencia al UIActivityIndicator, debe agregar una etiqueta

, p. en viewDidLoad

UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; 
spinner.center = CGPointMake(160, 240); 
spinner.tag = 12; 
[self.view addSubview:spinner]; 
[spinner startAnimating]; 
[spinner release]; 

en el método loadingFinished (independientemente del método que se llama cuando se termine de cargar)

[[self.view viewWithTag:12] stopAnimating]; 
+0

Esto no funciona porque DetailsViewController no 'muestra' hasta que toda la información se haya completado. –

+0

La vista de detalles no se muestra porque está cargando los datos de forma síncrona, lo que bloquea el hilo. necesita realizar esta solicitud en segundo plano si desea mostrar un indicador de actividad de animación – wattson12

+0

y ¿cómo lo haría? –

3

Es necesario hacer algún trabajo en un subproceso en segundo plano. Si la siguiente línea es la que se toma el tiempo:

detailViewController.item = [rssItems objectAtIndex:floor(indexPath.row/2)]; 

entonces se podría hacer esto en el fondo con GCD:

UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; 

dispatch_async(dispatch_get_global_queue(0, 0), ^{ 
    // This is the operation that blocks the main thread, so we execute it in a background thread 
    id item = [rssItems objectAtIndex:floor(indexPath.row/2)]; 

     // UIKit calls need to be made on the main thread, so re-dispatch there 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      detailViewController.item = item; 
      [spinner stopAnimating]; 
     }); 
}); 

Y 1 a @ wattson12 - es necesario agregar la ruleta a la nueva vista en su lugar. De forma alternativa, puede agregar la ruleta a la vista actual y, en su lugar, poner la llamada pushViewController en su bloque de cola principal de GCD.

Punto final: querrás quitar la ruleta de su supervista una vez que dejes de animarla. Alternativamente, puede tener una instancia única de la ruleta y establecer hidesWhenStopped en SÍ.

0

Ésta es una rueda que gira sobre una vista borrosa de esperar:

func blurScence(){ 
    let blurEffect: UIBlurEffect = UIBlurEffect(style: .Dark) 
    let blurView: UIVisualEffectView = UIVisualEffectView(effect: blurEffect) 
    blurView.translatesAutoresizingMaskIntoConstraints = false 
    blurView.frame = self.view.frame 

    let spinner = UIActivityIndicatorView(activityIndicatorStyle:.White) 
    spinner.center=blurView.center 
    blurView.addSubview(spinner) 
    spinner.startAnimating() 

    self.view.addSubview(blurView) 
} 
Cuestiones relacionadas