2013-12-18 14 views
8

Sto provando a configurare uno UIPageViewController che può scorrere all'infinito caricando dinamicamente le visualizzazioni di pagina tramite un pull di dati NSUrlConnection. Inizio con 3 visualizzazioni: prev, curr, next; e caricare una vista aggiuntiva quando viene raggiunta la prima o l'ultima vista nell'array pageData.Scorrimento infinito UIPageViewController

Il problema è che carico le viste aggiuntive in viewControllerBeforeViewController o viewControllerAfterViewController. Sembra che questi metodi possano essere chiamati 2-3 volte quando si fa un singolo passaggio tra le pagine. Possono anche essere chiamati durante un half-swipe che non finisce mai la transizione della pagina. Ciò può significare che i precarichi multipli iniziano a essere eseguiti prematuramente. Quindi in qualche modo lo pageViewController dimentica la posizione corrente.

[self.pageViewController setViewControllers:@[[self.pageData objectAtIndex:gotoIdx]] direction:direction animated:NO completion:nil]; 

Questa linea è utilizzata sotto per segnalare un'aggiunta di dati nel pageViewController, ed andare eh visualizzazione appropriata. Quando inizio a usarlo, invece di andare alla vista precedente/successiva con un colpo, inizia a saltare a viste apparentemente casuali. Una volta che ho iniziato ad andare avanti quando si fa scorrere all'indietro ...

C'è un luogo più appropriato per eseguire il preload che viene chiamato una sola volta al termine della transizione della pagina? E, la linea sopra deve essere chiamata, o c'è un modo più affidabile per assicurarsi che vada alla pagina corretta? Mi sento frustrato cercando di collegarlo qui.

// the init line, somewhere early on. uses Scoll style 
self.pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationVertical options:nil]; 

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController { 
    NSUInteger index = [self.pageData indexOfObject:viewController]; 
    if(index == 1){ 
     // if loading last one on start, preload one more in advance 
     [self loadSecondaryCalData:-1 endView:[[self viewControllerAtIndex:index-1] retain]]; 
    } else if ((index == 0) || (index == NSNotFound)) { 
     return nil; 
    } 

    index--; 
    return [self viewControllerAtIndex:index]; 
} 

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

    NSUInteger index = [self.pageData indexOfObject:viewController]; 
    if(index == [self.pageData count]-2){ 
     [self loadSecondaryCalData:1 endView:[[self viewControllerAtIndex:index+1] retain]]; // if last one, preload one more in advance 
    } else if (index == NSNotFound) { 
     return nil; 
    } 

    index++; 
    if (index == [self.pageData count]) { 
     return nil; 
    } 
    return [self viewControllerAtIndex:index]; 
}  


- (void)loadSecondaryCalData:(int)howMany endView:(CalendarViewController*)endView { 
    // initiate NSURLConnection async request for view data 
} 

- (void)loadSecondaryCals: (NSDictionary*)data { 
    // callback for async request 

    // ... process view, cal 

    // add new object to page data, at start or end 
    if(next){ 
     [self.pageData addObject:cal]; 
     gotoIdx = [self.pageData count]-2; 
     direction = UIPageViewControllerNavigationDirectionForward; 
    } else { 
     [self.pageData insertObject:cal atIndex:0]; 
     gotoIdx = 1; 
     direction = UIPageViewControllerNavigationDirectionReverse; 
    } 

    [self.pageViewController setViewControllers:@[[self.pageData objectAtIndex:gotoIdx]] direction:direction animated:NO completion:nil]; 

// alternate method to above line 
/* 
__block CalendarPageViewViewController *blocksafeSelf = self; 
__block int blocksafeGotoIdx = gotoIdx; 
__block UIPageViewControllerNavigationDirection blocksafeDirection = direction; 
[self.pageViewController setViewControllers:@[[self.pageData objectAtIndex:gotoIdx]] direction:direction animated:YES completion:^(BOOL finished){ 
    if(finished) 
    { 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      [blocksafeSelf.pageViewController setViewControllers:@[[blocksafeSelf.pageData objectAtIndex:blocksafeGotoIdx]] direction:blocksafeDirection animated:NO completion:nil]; 
     }); 
    } 
}]; 
*/ 


} 

UPDATE:

Grazie alla risposta veloce sotto, fanno riferimento a una grande funzione che non ero a conoscenza. Ecco il metodo di precaricamento che viene chiamato così alla perfezione solo una volta al completamento della transizione. Questo sembra aver notevolmente chiarito l'inaffidabile salto di vedute e la dimenticanza della posizione. Grazie @ha!

// function to detect if we've reached the first or last item in views 
// detects for full completion only 
- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed { 

    if(completed == TRUE && [previousViewControllers count] > 0 && [pageData count] > 1){ 
     CalendarViewController *firstCal = [pageData objectAtIndex:0]; 
     CalendarViewController *lastCal = [pageData objectAtIndex:([pageData count]-1)]; 

     CalendarViewController *prevCal = [previousViewControllers objectAtIndex:0]; 
     CalendarViewController *currCal = [[pageViewController viewControllers] objectAtIndex:0]; 

     NSLog(@"transition completed: %@ -> %@", prevCal.week_day_date, currCal.week_day_date); 
     if(currCal == firstCal){ 
      // preload on begining 
      [self loadSecondaryCalData:-1 endView:firstCal]; 
     } else if(currCal == lastCal){ 
      // preload to end 
      [self loadSecondaryCalData:1 endView:lastCal]; 
     } 
    } 
} 

risposta

5

penso che devi fare le chiamate di carico all'interno pageViewController:didFinishAnimating:previousViewControllers:transitionCompleted: gestore. Questo metodo verrà chiamato al termine dell'animazione e il nuovo ViewController è diventato attivo.

+0

Grazie, ha funzionato alla grande! Vedi l'aggiornamento sopra per la soluzione. Tanto più pulito in questa funzione. – Miro

+0

Swift 3: func pageViewController (_ pageViewController: UIPageViewController, didFinishAnimated finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completato: Bool) –

Problemi correlati