Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIPageViewController navigates to wrong page with Scroll transition style

My UIPageViewController was working fine in iOS 5. But when iOS 6 came along, I wanted to use the new scroll transition style (UIPageViewControllerTransitionStyleScroll) instead of the page curl style. This caused my UIPageViewController to break.

It works fine except right after I've called setViewControllers:direction:animated:completion:. After that, the next time the user scrolls manually by one page, we get the wrong page. What's wrong here?

like image 207
matt Avatar asked Oct 17 '12 16:10

matt


3 Answers

My workaround of this bug was to create a block when finished that was setting the same viewcontroller but without animation

__weak YourSelfClass *blocksafeSelf = self;     
[self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:^(BOOL finished){
            if(finished)
            {
                dispatch_async(dispatch_get_main_queue(), ^{
                    [blocksafeSelf.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:NULL];// bug fix for uipageview controller
                });
            }
        }];
like image 144
George Tsifrikas Avatar answered Oct 08 '22 03:10

George Tsifrikas


This is actually a bug in UIPageViewController. It occurs only with the scroll style (UIPageViewControllerTransitionStyleScroll) and only after calling setViewControllers:direction:animated:completion: with animated:YES. Thus there are two workarounds:

  1. Don't use UIPageViewControllerTransitionStyleScroll.

  2. Or, if you call setViewControllers:direction:animated:completion:, use only animated:NO.

To see the bug clearly, call setViewControllers:direction:animated:completion: and then, in the interface (as user), navigate left (back) to the preceding page manually. You will navigate back to the wrong page: not the preceding page at all, but the page you were on when setViewControllers:direction:animated:completion: was called.

The reason for the bug appears to be that, when using the scroll style, UIPageViewController does some sort of internal caching. Thus, after the call to setViewControllers:direction:animated:completion:, it fails to clear its internal cache. It thinks it knows what the preceding page is. Thus, when the user navigates leftward to the preceding page, UIPageViewController fails to call the dataSource method pageViewController:viewControllerBeforeViewController:, or calls it with the wrong current view controller.

I have posted a movie that clearly demonstrates how to see the bug:

http://www.apeth.com/PageViewControllerBug.mov

EDIT This bug will probably be fixed in iOS 8.

EDIT For another interesting workaround for this bug, see this answer: https://stackoverflow.com/a/21624169/341994

like image 35
matt Avatar answered Oct 08 '22 04:10

matt


Here is a "rough" gist I put together. It contains a UIPageViewController alternative that suffers from Alzheimer (ie: it doesn't have the internal caching of the Apple implementation).

This class isn't complete but it works in my situation (namely: horizontal scroll).

like image 3
Paul de Lange Avatar answered Oct 08 '22 04:10

Paul de Lange