2013-02-26 6 views
6

Ho cercato molti, molti posti e non ho ancora trovato un buon codice di esempio che mostra come precaricare la pagina "successiva" in un UIPageViewController. Ci sono alcune risposte su SO che illustrano alcuni modi teorici per farlo (vedi this question) ma nessuno deve ancora pubblicare un esempio funzionante.Precarica pagina successiva in UIPageViewController

Nel flusso di lavoro della mia app sto visualizzando 1 pagina per schermo e voglio avere la schermata "successiva" precaricata perché così com'è, scorrere alla pagina successiva può essere molto lento, a volte richiede 2 passaggi (se si scorre troppo velocemente) affinché la pagina successiva sia visualizzata e visualizzata. Ciò fornisce un'esperienza utente negativa. Non mi interessa davvero il precaricamento del "precedente" o di qualsiasi altro schermo poiché il flusso di lavoro tipico sarà che gli utenti rimangono su uno schermo per un po 'prima di passare alla schermata successiva (a destra). Sto usando l'animazione della diapositiva (non rannicchiata). Creo tutte le viste programmaticamente e non uso affatto IB.

Ho provato a memorizzare alcuni UIViewControllers in un NSMutableArray e caricare i controller da lì, ma è complicato lavorare correttamente e non sembra velocizzare nulla. Ci deve essere un buon modo per farlo.

Qualsiasi aiuto è molto apprezzato.

+1

Hai trovato una soluzione per questo? Ho lo stesso problema, ottenendo un ritardo notevole quando si passa al successivo controller della vista. – mattsson

+0

Sort of, ma la risposta è molto specifica per la mia implementazione. Poiché ho lavorato molto con UIPageViewController da quando ho postato questa domanda, ho scoperto che è un argomento molto delicato. Fondamentalmente, i miei problemi avevano più a che fare con l'interrogazione del DB per i dati giusti da mostrare, il che rallentava ogni pagina. Sono stato in grado di ottimizzare i giri delle mie pagine pre-calcolando i dati dal DB e disegnando le mie viste usando Auto Layout invece di scherzare con i frame - questo ha aiutato molto. In secondo luogo avevo molte immagini da mostrare, quindi le ho archiviate in un NSMutableArray direttamente sul controller di visualizzazione "principale" (padre di scorrimento). – DiscDev

+0

La mia "soluzione" ha finito per essere ... continua ad aspettare che Apple esca con i telefoni più veloci .... hahaha. Su iPhone 6/6s, non c'è più lag.Ho ottimizzato parte del codice di recupero del database da eseguire una volta quando il controller di pagina è stato creato e questo ha aiutato molto, ma i miglioramenti principali della velocità sono derivati ​​da processori più veloci e più RAM e il supporto di phasing out per iPhone 4/4s =) – DiscDev

risposta

0

È necessario eseguire il debug del codice utilizzando, ad esempio, Time Profiler of Instruments. In questo modo, troverai quale oggetto ha il tempo di esecuzione più alto. Forse non è collegato a UIPageViewController ma alla vista all'interno delle pagine.

2

Ho risolto per il mio caso in un po 'di hack. Per ogni ContentView, ho unoall'interno di uno UIScrollView per lo zoom. Il mio problema era che all'avvio dell'applicazione, se l'utente eseguiva lo zoom prima di eseguire lo scorrimento, passare alla pagina successiva mentre lo zoom non funzionava troppo bene. Io uso il seguente codice (Swift 1.2) per risolvere questo problema. Come ho già detto, è un po 'un trucco.

var layoutsubs = false 

override func viewDidLoad() { 
    super.viewDidLoad() 
    //Other code for implementing pageViewController omitted 

    //add pageViewController to main view 
    self.addChildViewController(pageViewController) 
    self.view.addSubview(pageViewController.view) 
    pageViewController.didMoveToParentViewController(self) 

    //Load to the viewController after the starting VC, then go back to the starting VC 
    var viewControllers = [afterVC] 
    pageViewController.setViewControllers(viewControllers as [AnyObject], direction: .Forward, animated: true, completion: nil) 
    viewControllers = [startingVC] 
    pageViewController.setViewControllers(viewControllers as [AnyObject], direction: .Reverse, animated: true, completion: nil) 
} 

override func viewWillLayoutSubviews() { 
    //Load the viewController before the starting VC then go back to the starting VC 
    //viewWillLayoutSubviews() is called multiple times, so do this only once 
    if !layoutsubs { 
     let startingVC = self.viewControllerAtIndex(imageIndex) as ContentViewController 
     let beforeVC = pageViewController(pageViewController, viewControllerBeforeViewController: startingVC) as! ContentViewController 

     var viewControllers = [beforeVC] 
     pageViewController.setViewControllers(viewControllers as [AnyObject], direction: .Reverse, animated: true, completion: nil) 
     viewControllers = [startingVC] 
     pageViewController.setViewControllers(viewControllers as [AnyObject], direction: .Forward, animated: true, completion: nil) 
     layoutsubs = true 
    } 
} 

Essenzialmente, si carica il controller di vista prima e dopo il controller della vista di partenza. Lo faccio impostando ciascuno sul VC per vedere tramite setViewControllers(_:direction:animated:completion:) (see ref), quindi tornando al controller della vista iniziale. Perché questo è in due diverse funzioni? Bene, se lo metti tutto in uno, verrà caricato solo uno dei due controller di visualizzazione accanto al VC iniziale. Questo potrebbe essere desiderabile in alcuni casi, ma avevo bisogno di caricare tutti e tre i VC (prima, dopo e dopo).

Non sono sicuro di quanto questo metodo possa funzionare se lo UIPageViewController è già stato caricato. Ad esempio, se è necessario caricare la pagina 2 lontano dalla pagina visualizzata, dopo alcuni passaggi. Potrebbe saltare se lo inserisci in willTransitionToViewControllers().

+0

Come funziona se non hai una quantità fissa di VC? C'è un modo per precaricarli tutti in una volta, quindi non ci sono problemi? Grazie! – Jacob

+0

@Jacob: se non si dispone di una quantità fissa di VC, è necessario prima verificare se ci sono VC prima e dopo il VC selezionato. Se c'è solo un VC dopo di esso, userete il codice solo in 'viewDidLoad()', e 'viewWillLayoutSubviews()' non sarà usato. Se c'è solo un VC prima di esso, userai il codice in 'viewWillLayoutSubviews()', e tutto in 'viewWillLoad' iniziando con' // Carica sul viewController dopo il VC iniziale ... 'il commento verrà rimosso. In questo caso potresti essere in grado di andare al precedente VC in 'viewDidLoad()'. Non sono sicuro di come precaricare tutti i VC, mi dispiace. –

+0

ciao puoi fornire il codice completo inizializzando pageViewController per finalizzarlo –