2013-12-18 20 views
8

Tôi đang cố thiết lập UIPageViewController có thể cuộn vô hạn bằng cách tự động tải lượt xem trang qua một lần kéo dữ liệu NSUrlConnection. Tôi bắt đầu với 3 lượt xem: prev, curr, next; và tải chế độ xem bổ sung khi chế độ xem đầu tiên hoặc cuối cùng trong mảng pageData.Cuộn vô hạn UIPageViewController

Sự cố là tôi tải các chế độ xem bổ sung trong viewControllerBeforeViewController hoặc viewControllerAfterViewController. Dường như các phương thức này có thể được gọi 2-3 lần khi thực hiện một lần vuốt giữa các trang. Họ cũng có thể được gọi trong khi vuốt một nửa mà không bao giờ kết thúc quá trình chuyển đổi trang. Điều này có nghĩa là nhiều lần tải trước bắt đầu được thực hiện sớm. Sau đó, bằng cách nào đó, pageViewController sẽ quên vị trí hiện tại.

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

Đường này được sử dụng bên dưới để báo hiệu bổ sung dữ liệu trong pageViewController và để chuyển đến chế độ xem phù hợp. Khi tôi bắt đầu sử dụng nó, thay vì chuyển sang chế độ xem trước/tiếp theo bằng thao tác vuốt, nó bắt đầu nhảy đến các chế độ xem có vẻ ngẫu nhiên. Khi tôi bắt đầu tiến lên phía trước khi vuốt ngược lại ...

Có nơi thích hợp hơn để thực hiện tải trước chỉ được gọi một lần sau khi quá trình chuyển đổi trang hoàn tất không? Và, dòng bên trên có được gọi hay không, hoặc có cách nào đáng tin cậy hơn để đảm bảo nó đi đúng trang không? Cảm thấy thất vọng khi cố gắng nối dây ở đây.

// 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:

Nhờ có sự phản ứng nhanh dưới đây, tham khảo một chức năng tuyệt vời, tôi đã không nhận thức được. Đây là phương pháp tải trước hoàn toàn chỉ được gọi một lần khi hoàn thành quá trình chuyển đổi. Điều này dường như đã làm sáng tỏ rất nhiều việc nhảy không đáng tin cậy xung quanh quan điểm và quên vị trí. Cảm ơn @sha!

// 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]; 
     } 
    } 
} 

Trả lời

5

Tôi nghĩ bạn cần thực hiện cuộc gọi tải trong bộ xử lý pageViewController:didFinishAnimating:previousViewControllers:transitionCompleted:. Phương thức này sẽ được gọi khi animation đã hoàn thành và ViewController mới trở thành một active.

+0

Cảm ơn, điều này đã hiệu quả! Xem cập nhật ở trên để biết giải pháp. Vì vậy, sạch hơn nhiều trong chức năng này. – Miro

+0

Swift 3: func pageViewController (_ pageViewController: UIPageViewController, didFinishAnimating đã hoàn tất: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) –

Các vấn đề liên quan