2015-06-13 10 views
11

Nella vista principale della mia app ho una vista tabella e due celle prototipo. Ho configurato i segues per ogni cella usando lo storyboard. Nel controller della vista, sovrascrivo prepareForSegue per passare le informazioni sulla cella selezionata alla vista di destinazione.iOS si blocca per molti secondi prima di mostrare una nuova vista

La vista di destinazione non è particolarmente complessa e certamente non richiede alcuna elaborazione pesante da caricare.

PROBLEMA

Quando si tocca su una cella del controller principale per la prima volta, la vista di destinazione appare dopo un lungo ritardo, da 5 a 40 secondi.

EDIT # 2: rubinetti successivi sono generalmente più veloci

Nota che:

  • Se si tocca sullo stesso cellulare nuovo prima è apparsa la vista di destinazione, questo innesca la vista di destinazione apparire immediatamente.
  • Come sopra, ma toccando una cella diversa, la vista viene visualizzata immediatamente ma con i dati della prima cella.
  • Come sopra, ma toccando un controllo diverso (senza sequenze associate), la vista di destinazione viene immediatamente visualizzata.
  • I "tocchi" successivi generalmente manifestano meno ritardo.
  • Il Time Profiler - per quello che posso vedere - mostra che assolutamente nulla sta accadendo durante quei molti secondi di ritardo.
  • ho cercato diverso tipo di segues, ma fatto differenza
  • mostra Alcuni di println che la seguente sequenza di eventi si verifica:

    • nella vista principale, prepareForSegue viene eseguito (senza ritardi)
    • poi il viewDidLoad destinazione viene eseguito (senza ritardi)
    • ... lungo ritardo ...
    • il punto di vista di raccolta e tabella nel des avviare il controller di tinga invocando i metodi relativi all'origine dati per recuperare i dati dal controller. appare
    • la vista infine (con un'animazione indesiderato, BTW, ma questo è un problema diverso)

Da quello che ho letto su questo argomento, ho il sospetto che il problema è potenzialmente legato ad alcune delle sopra le operazioni che si verificano in un thread in background.

Qualche idea su cosa potrei fare male?

EDIT # 1: aggiunto un certo codice

Nel regolatore di vista principale le segues sono stati collegamento mediante la story board (CTRL-trascinare le due cellule prototipo nella vista di destinazione).

Il codice sembra un po 'come di seguito:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) 
{ 
    var assetIndex = assetsTable.indexPathForSelectedRow()?.row 

    println("prepare for segue - start: \(assets[assetIds[assetIndex!]]!.Name)") 

    if let destination = segue.destinationViewController as? AssetThingsListViewController 
    { 
     destination.bundlesRepository = bundlesRepository! 
     destination.asset = assets[assetIds[assetIndex!]] 
    } 

    println("prepare for segue - end") 
} 

EDIT # 3 ho fatto un progetto di esempio disponibile sul BitBucket

+1

Penso che questo sia un bug. Avevo sempre questo successo anche a me ogni volta che facevo un seguito per la prima volta. Iniziato con iOS 8. –

+0

Hai provato a eseguire l'app in modalità di rilascio? Immagino che vedrai questo comportamento solo in modalità di debug. –

+0

Sfortunatamente continua anche in modalità di rilascio. –

risposta

10

Ho controllato il tuo progetto. E anche se non sono riuscito a trovare nient'altro, sospetto anche che sia un problema con il threading.

sono riuscito a risolvere il problema mediante l'attuazione di un delegato per la tableview e presentare il nuovo controller in codice:

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { 

    let destination = storyboard?.instantiateViewControllerWithIdentifier("BuilderToysListViewController") as! BuilderToysListViewController 
    destination.botsRepository = botsRepository! 
    destination.builder = builders[builderIds[indexPath.row]] 

    dispatch_async(dispatch_get_main_queue(), {() -> Void in 
     self.presentViewController(destination, animated: true) {() -> Void in 

     } 
    }) 

} 

Avviso è stato il set l'id vista del regolatore storyboard: BuilderToysListViewController e anche impostare il delegato Tableview . Non dimenticare di rimuovere i segues.

alla fine per dissmis la vista nel nuovo uso View Controller di questo codice:

@IBAction func backButton(sender: AnyObject) 
{ 
    dismissViewControllerAnimated(true, completion: {() -> Void in 

    }) 
//  performSegueWithIdentifier("segueToysByBuilder", sender: nil)   

} 

questo permetterebbe di chiudere correttamente la vista invece di creare a torto uno nuovo.

+0

Grazie a @pteofil. Sembra che abbia colpito un bug di iOS 8. https://forums.developer.apple.com/message/12349 –

+0

Qualcuno può spiegare cosa sta facendo il codice sopra? Ho lo stesso problema con alcuni tocchi in ritardo e altri normali. Non riconosco il botsRepository o il codice di spedizione e non voglio integrare codice nella mia app senza comprenderlo. Tuttavia, voglio un'app che non abbia ritardi frustranti !! Qualcuno può spiegare cosa sta facendo questo codice/perché aiuta? Grazie! @pteofil –

+0

Il codice precedente presenta semplicemente il nuovo controller in codice quando viene toccata una cella, invece di impostare semplicemente le cose nello storyboard. Nel tuo caso puoi saltare la parte che imposta il botsRepository e il builder.Sono solo le proprietà del rispettivo controller presentato. Il 'dispatch_async' tuttavia è necessario, essendo il modo di chiamare del codice su un thread specifico. Tutte le modifiche all'interfaccia utente devono essere fatte sul thread principale. E normalmente questo è il caso di cose create nello storyboard. Ma ci sono bug, e in questo caso presento il nuovo controller sul thread principale per sicurezza – pteofil

0

Difficile da dire se non si registra il codice che sta rispondendo alla tocca la cella e presenta il nuovo controller di visualizzazione.

Una causa comune di lunghi ritardi nelle modifiche all'interfaccia utente (o la modifica dell'interfaccia utente non si verifica mai) sta tentando di apportare modifiche all'interfaccia utente da un thread in background. È possibile che il tuo codice che sta invocando il seguito sia in esecuzione su un thread diverso? Puoi dirlo facilmente impostando un breakpoint su quel codice e osservando il numero del thread quando si rompe. Se il numero del thread è 0, stai utilizzando il thread principale. Se si tratta di un altro numero di thread, questo è il tuo problema.

+0

Inoltre, ho realizzato che i successivi "tocchi" sono ** generalmente ** senza indugio, ma ho visto anche casi di ritardi consistenti anche in quelli successivi. –

Problemi correlati