2012-01-24 19 views
11

Ho un UITableView che da un feed RSS esterno.Animate Spinner quando si carica una nuova pagina

Quando si seleziona una riga utilizza navigationController e scorre da destra, il problema è che il feed RSS contiene immagini quindi può richiedere alcuni secondi per caricare e senza alcuna indicazione di ciò che sta accadendo si può sbagliare per un crash dell'applicazione.

Ho deciso di aggiungere uno spinner per sapere che la nuova pagina è in fase di caricamento.

Ecco il mio codice:

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"; 
} 

Ci sono due problemi con questo codice.

  1. Lo Spinner non è attivo fino a dopo il caricamento della nuova pagina.
  2. Lo Spinner non si disabilita una volta caricato.

Se qualcuno potesse aiutarmi con questo problema, sarei davvero grato.

+0

penso che stai ancora manca il codice dove poi indicatore di attività di vista viene arrestato/rimosso. Inoltre: come stai caricando le immagini? Se si utilizza un metodo di blocco (ad esempio uno che non viene eseguito in un thread in background), verrà bloccato l'intero ciclo principale che significa: nessuna interazione dell'utente, nessuna animazione ecc (che spiegherebbe questo comportamento). Se questo è il caso, dovresti davvero passare al caricamento asincrono. –

+0

@TriPhoenix Come fai a sapere se si tratta di un metodo di blocco o no? ho aggiunto nel codice su DetailsViewController.m –

+0

Puoi dire come funziona la funzione: le funzioni di blocco restituiscono immediatamente il valore, in questo caso 'initWithContentsOfURL' avrà messo i dati nel tuo' NSData'so la funzione non può restituire prima di aver restituito questi dati. Le richieste asincrone sono più complesse nel senso che si avvia la richiesta e non si avrà il risultato restituito, ma la richiesta richiamerà una funzione di callback sul proprio codice al termine. Ci sono alcuni framework come ASIHTTPRequest che rendono questo più facile o puoi usare NSURLConnection e farlo da solo. –

risposta

23

Si sta aggiungendo la vista indicatore di attività alla vista del controllore che sta spingendo il controller vista di dettaglio, in modo da non vedere comunque

provare a spostare il secondo gruppo di codice al metodo viewDidLoad di DetailsViewController, è puoi chiamare stopAnimating sull'indicatore di attività quando hai finito di caricare. Per ottenere un riferimento a UIActivityIndicator è necessario aggiungere un tag

ad es. in viewDidLoad

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

nel metodo loadingFinished (a seconda di quale metodo viene chiamato una volta terminato il caricamento)

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

Questo non funziona perché DetailsViewController non 'mostra' fino a quando tutte le informazioni sono state caricate. –

+0

la vista dettagli non viene visualizzata perché si stanno caricando i dati in modo sincrono, il che blocca il thread. è necessario eseguire questa richiesta in background se si desidera mostrare un indicatore di attività di animazione – wattson12

+0

e come si farebbe? –

3

Hai bisogno di fare un certo lavoro in un thread in background. Se la seguente riga è quella che prende il tempo:

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

allora si potrebbe fare questo in background 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]; 
     }); 
}); 

E 1 a @ wattson12 - è necessario aggiungere il filatore alla nuova vista invece. In alternativa puoi aggiungere lo spinner alla vista corrente e invece inserire la chiamata pushViewController nel tuo blocco di coda principale GCD.

Punto finale: ti consigliamo di rimuovere lo spinner dal suo superview una volta che lo interrompi. In alternativa, puoi avere una singola istanza dello spinner e impostare hidesWhenStopped su YES.

0

Questa è una ruota che gira su una vista offuscata a Swift:

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) 
} 
Problemi correlati