Reinhard Männer
Reinhard Männer

Reputation: 15217

iOS: UIPagesViewController sometimes does not display correctly when using gestures for page switching

I have a UIPagesViewController with 2 pages. One page is shown here:
enter image description here
The pages can be switched by gesture or by clicking a button in the toolbar.

Switching by button works always correctly using the method

-(void)switchViewControllers
{
    if (self.pageIndex == 1) {
        self.pageIndex = 0;
        [self setViewControllers:@[self.gameControllers[0]] direction:UIPageViewControllerNavigationDirectionReverse animated:YES completion:nil];
    } else {
        self.pageIndex = 1;
        [self setViewControllers:@[self.gameControllers[1]] direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:nil];
    }
}

However switching by gesture works only most of the time correctly, but sometimes the resulting scene looks like one of the following images:
enter image description here enter image description here enter image description here
If the scene looks like the left image above, the half button visible does not work. But the page can still be switched by gesture, and everything works again.
The problem happens on the simulator and on the device.
I have no idea what could be wrong, nor how to avoid the problem. Any hint is highly welcome.

EDIT (due to Bartek's answer):
The problem occurs even if the pages are never switched programmatically.

UPDATE:
I realized now the following: If the page view is in the state shown in the left one of the 3 faulty scenes, and I drag it a few pixels right and let go, the vertical bar that can be seen on all 3 images right disappears, and the image is shown correctly and is shifted back to the correct position. If I then drag it a little left and let go, that vertical bar is shown again. So this obviously a UIPageViewController bug.

Upvotes: 0

Views: 210

Answers (2)

Reinhard Männer
Reinhard Männer

Reputation: 15217

Here is the solution that worked for me:

Actually I had 2 separate problems.

1) The vertical stripes that you can see in the images above.
My view controllers that are presented by the UIPageViewController have an UIImageView subview that covers the whole view, used for a background image (the dotted background above). I used during development an image of size 2480x3507 with file name "Fond1.jpg". When I instead assign an image of size 640x1092 with file name "[email protected]", the stripes are gone.

2) The black images shown above.
This apparently happened when I did page switching very fast, i.e. so fast that the 1st switching animation was not yet finished when the 2nd one was initiated. I found here a solution that apparently works also for me (I did not have such problems since then).

Actually I think both problems are caused by bugs in iOS: When it is possible to use jpg images, they should be handled correctly. And the UIPageViewController should be able to handle the situation that one tries very fast page switching by itself.

Upvotes: 1

Bartek Chlebek
Bartek Chlebek

Reputation: 1665

UIPageViewController is buggy as hell, especially if you mix switching pages by gesture with switching from code.
What you might want to try is to force UIPageViewController to reload its cache when switching pages by code (not by gesture). So, for example:

-(void)switchViewControllers
{
    // Resetting dataSource will cause UIPageViewControllerDataSource to rebuild its view controller stack cache
    id<UIPageViewControllerDataSource> dataSource = self.dataSource;
    self.dataSource = nil;
    self.dataSource = dataSource;

    if (self.pageIndex == 1) {
        self.pageIndex = 0;
        [self setViewControllers:@[self.gameControllers[0]] direction:UIPageViewControllerNavigationDirectionReverse animated:YES completion:nil];
    } else {
        self.pageIndex = 1;
        [self setViewControllers:@[self.gameControllers[1]] direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:nil];
    }
}

This looks hideous, but does the trick.
To elaborate, UIPageViewController seems to have some sort of underlying cache for view controllers stack. This cache appears to go out of sync when we switch pages not by gesture but by code. I wouldn't be surprised if it were a bug, singe UIPageViewController is full of those.

So, forcing UIPageViewController to reload its cache when settings viewControllers helps. The best way to achieve that is to reset the dataSource, as in the example above.

I hope this helps.

And that you don't rely on UIPageViewController too much :)

Upvotes: 0

Related Questions