2015-08-16 15 views
5

Ho avuto difficoltà per tutto il weekend con questo problema e ho trascorso molto tempo a cercare su Google la soluzione senza alcun successo.UIPageViewController non tiene traccia dell'indice della pagina

Il mio caso d'uso è piuttosto semplice e non posso credere quanto sia difficile far funzionare correttamente un comportamento così banale.

La mia app è un semplice flusso impaginato in cui gli utenti passano a sinistra oa destra per visualizzare la pagina successiva o precedente. Ho un UIPageViewController e ogni pagina contiene un UITableView. Ho avuto problemi cercando di tenere traccia della pagina indice all'interno delle funzioni viewControllerAfterViewController e viewControllerBeforeViewController per le ragioni qui: PageViewController delegate functions called twice

Ho provato seguendo tutte le soluzioni alternative suggerite per questo problema (tenere traccia dell'indice all'interno willTransitionToViewControllers e didFinishAnimating) ma questo non risolve il mio problema dato che viewController * Le funzioni ViewController devono ancora restituire un viewController e dal momento che vengono inizialmente chiamati due volte, il primo viewController restituito sembra essere quello che viene utilizzato e il secondo passaggio non sembra avere qualche effetto

Anche se ho visto molte domande e blog su questo problema, non ho visto un solo esempio che mostra come restituire in modo coerente il viewController corretto dalle funzioni ViewController viewController * e saremo grati per un esempio. Il problema principale a cui non riesco a vedere una soluzione è come determinare il prossimo indice all'interno di willTransitionToViewControllers se ho solo una singola viewController il cui contenuto è aggiornato dinamicamente al caricamento della pagina. Mi sembra un problema di pollo e uova; Ho bisogno di capire quale contenuto aggiornare la pagina, ma per farlo ho bisogno di sapere qual è l'indice della pagina (che è parte del contenuto).

Modifica Ecco una versione distillata del codice interessato:

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    _pageViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"PageViewController"]; 
    _pageViewController.dataSource = self; 
    _pageViewController.delegate = self; 
    [self.view addSubview:_pageViewController.view]; 

    PageContentViewController *startingPage = [self viewControllerAtIndex:0]; 

    NSArray *viewControllers = @[startingPage]; 
    [_pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil]; 

} 

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController { 
    // Don't do any index calculations as the result is inconsistent 
    return [self viewControllerAtIndex:nextIndex]; 
} 

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController { 
    // Don't do any index calculations as the result is inconsistent 
    return [self viewControllerAtIndex:nextIndex]; 
} 

- (void)pageViewController:(UIPageViewController *)pageViewController willTransitionToViewControllers:(NSArray *)pendingViewControllers { 
    // This value never changes because the global _pageViewContentController hasn't been updated yet 
    nextIndex = [((PageContentViewController *)pendingViewControllers[0]) pageIndex]; 
} 

- (PageContentViewController *)viewControllerAtIndex:(NSUInteger)index { 
    _pageContentViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"PageContentViewController"]; 
    _pageContentViewController.pageIndex = index; 
    _pageContentViewController.title = index; 

    return _pageContentViewController; 
} 

ho il debug l'ordine in cui queste funzioni vengono chiamati e ci si aspetta il _pageViewContentController globale per essere popolato con i dati corretti dopo che la pagina è passata.

Edit 2 Per dare qualche dettaglio in più sul mio problema; ciascuna delle mie pagine contiene un titolo e una tabella di collegamenti web. Facendo clic su un collegamento si apre un WebViewController per visualizzare la pagina Web selezionata. Con la soluzione di Yunus di seguito, tutto viene visualizzato correttamente (il titolo e i collegamenti vengono visualizzati come previsto) ma il problema si presenta quando si fa clic su un collegamento poiché questo carica un collegamento dalla pagina successiva. Sembra che la fase di rendering della pagina si verifichi nel momento in cui i dati sono corretti, ma reinizializza il controller del contenuto della pagina con dati errati al termine del rendering, motivo per cui i dati effettivi del collegamento sono errati (anche se i dati renderizzati sono buoni).

+0

Puoi condividere alcune parti relative del codice? –

+0

@YunusErenGuzel - snippet di codice aggiunti. – bobby

+0

Come si apre questo WebViewController? All'interno di UIPageViewController o come modale o ecc.? –

risposta

3

Teniamo tutti i relativi contentViewControllers in un array

self.contentViewControllers = [NSMutableArray new]; 
for(int i=0; i< MAX_INDEX; i++) { 
    [self.contentViewControllers addObject:[self viewControllerAtIndex:0]]; 
} 

Poi quello che dobbiamo fare è quello di decidere quali visualizzare regolatore dovremmo mostrare dopo e prima di metodi

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController 
    viewControllerBeforeViewController:(UIViewController *)viewController 
{ 

    for(int i=0;i<self.contentViewControllers.count ;i++) 
    { 
    if(viewController == [self.contentViewControllers objectAtIndex:i]) 
    { 
     if(i-1 >= 0) 
     { 
     return [self.contentViewControllers objectAtIndex:i-1]; 
     } 
    } 
    } 
    return nil; 
} 

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController 
     viewControllerAfterViewController:(UIViewController *)viewController 
{ 

    for(int i=0;i<self.contentViewControllers.count ;i++) 
    { 
    if(viewController == [self.contentViewControllers objectAtIndex:i]) 
    { 
     if(i+1 < self.contentViewControllers.count) 
     { 
     return [self.contentViewControllers objectAtIndex:i+1]; 
     } 
    } 
    } 
    return nil; 
} 

Poi nel metodo di transizione

- (void)pageViewController:(UIPageViewController *)pageViewController willTransitionToViewControllers:(NSArray *)pendingViewControllers 
{ 
    UIViewController* viewController = [pendingViewControllers objectAtIndex:0]; 
    NSInteger nextIndex = [self.contentViewControllers indexOfObject:viewController]; 
    [self.pageControl setCurrentPage:nextIndex]; 
} 
+0

Ciao Yunus. Grazie per l'aiuto. Ho modificato il mio codice per provare il tuo suggerimento (questo è qualcosa che avevo già provato nel weekend ma senza successo). Nel tuo esempio, stai impostando il valore nextIndex ma non viene mai utilizzato da nessuna parte. Mi sto perdendo qualcosa qui? – bobby

+0

In realtà tengo quello vuoto per te a quello che vorresti comunque usare. Lo uso con SMPageControl per mantenere l'indice con '[self.pageControl setCurrentPage: nextIndex];' –

+0

Puoi usare questo ViewController per vedere come funziona. https://github.com/yunuserenguzel/sonicraph-ios/blob/master/sonicraph/View%20Controllers/SNCGoThroughViewController.m –