UIPageViewController in iOS6

In iOS6, in the methods of viewControllerAfterViewController and viewControllerBeforeViewController , if I return nil (to block page navigation when I'm on the first or last page), the application crashes with this exception:

'The number of available view controllers (0) does not match the required number (1) for the requested jump

In iOS5, everything works well.

+20
ios objective-c iphone uipageviewcontroller
Sep 24
source share
5 answers

I had the same problem. I found that the reason was replacing the delegate with a UIPanGestureRecognizer for the UIPageViewController, and no no. The gesture recognizer attribute called the undocumented method _gestureRecognizerShouldBegin: (note the upper underscore), which implements the UIPageViewController and apparently relies on the correct operation (read: not-crash). I completed the implementation of responsesToSelector: and forwardingTargetForSelector: in my class, which uses the UIPageViewController to pass the undocumented delegate method to the UIPageViewController without calling it (and almost certainly getting the app store check denied).

-(BOOL)respondsToSelector:(SEL)aSelector { if ([super respondsToSelector:aSelector]) return YES; else if ([self.pageViewController respondsToSelector:aSelector]) return YES; else return NO; } - (id)forwardingTargetForSelector:(SEL)aSelector { if ([super respondsToSelector:aSelector]) { return nil; } else if ([self.pageViewController respondsToSelector:aSelector]) { return self.pageViewController; } return nil; } 

My long-term solution would be to redesign the use of the UIPageViewController in such a way that I would not have to crowd out delegates of gesture recognizers.

+29
Sep 24 '12 at 10:10
source share

And, it was interesting why no one pointed out this error, which I took almost 2 nights to find out the solution.

OLD CODE (iOS 5.1): When you return nil on the first and last page, you will encounter an application crash. It works fine in iOS 5.1, but in iOS 6 it won't.

 - (UIViewController *)pageViewController: (UIPageViewController *)pageViewController viewControllerBeforeViewController: (UIViewController *)viewController { for (UIGestureRecognizer *recognizer in pageController.gestureRecognizers) { if ([recognizer isKindOfClass:[UITapGestureRecognizer class]]) { recognizer.enabled = NO; } } NSUInteger index = [self indexOfViewController: (MainViewController *)viewController]; if ((index == 0) || (index == NSNotFound)) { return nil; } index--; return [self viewControllerAtIndex:index]; } - (UIViewController *)pageViewController: (UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController { for (UIGestureRecognizer *recognizer in pageController.gestureRecognizers) { if ([recognizer isKindOfClass:[UITapGestureRecognizer class]]) { recognizer.enabled = NO; } } NSUInteger index = [self indexOfViewController: (MainViewController *)viewController]; if (index == NSNotFound) { return nil; } } 

SOLUTION (iOS 6): adding the gesture effect to the supervisor, just call the delegate named - (BOOL) gestureRecognizerShouldBegin: (UIGestureRecognizer *) gestureRecognizer. What I did is very simple, calculating the user's speed, turning the first page and the last page (I mean using the gesture recognizer), I denied scrolling. All you have to do is simply paste the following code and you MUST !.

 - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer { if (pageNum==0) { if ([(UIPanGestureRecognizer*)gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] && [(UIPanGestureRecognizer*)gestureRecognizer velocityInView:gestureRecognizer.view].x > 0.0f) { //NSLog(@"Swiping to left on 1st page is denied"); return NO; } if ([(UITapGestureRecognizer*)gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]] && [(UITapGestureRecognizer*)gestureRecognizer locationInView:gestureRecognizer.view].x < self.view.frame.size.width/2) { //NSLog(@"tapping to left on 1st page is denied"); return NO; } } else if(pageNum ==totalNoOfFiles-1) { if ([(UIPanGestureRecognizer*)gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] && [(UIPanGestureRecognizer*)gestureRecognizer velocityInView:gestureRecognizer.view].x < 0.0f) { //NSLog(@"Swiping to right on 1st page is denied"); return NO; } if ([(UITapGestureRecognizer*)gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]] && [(UITapGestureRecognizer*)gestureRecognizer locationInView:gestureRecognizer.view].x > self.view.frame.size.width/2) { //NSLog(@"Tapping to right on 1st page is denied"); return NO; } } return YES; } - (UIViewController *)pageViewController:(UIPageViewController*) pageViewController viewControllerBeforeViewController:(UIViewController *)viewController { int index = [self indexOfViewController:(ChildViewController *)viewController]; index--; return [self viewControllerAtIndex:index]; } - (UIViewController *)pageViewController: (UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController { int index = [self indexOfViewController:(ChildViewController *)viewController]; index++; return [self viewControllerAtIndex:index]; } 
+12
Oct 08
source share

This has been well discussed, but I have one thing to add. Think about why you appointed a gesture recognizer delegate. In my case, this was due to the fact that in some cases I wanted to prevent the recognition of gesture recognizers with the delegate gestureRecognizerShouldBegin:

But in iOS 6, where this problem occurs, there is a completely new way to do just that by implementing gestureRecognizerShouldBegin: in a UIView. (This is a new instance method of UIView in iOS 6.)

That way, I was able to accomplish what I did before without changing the delegate of the gesture recognizers.

+7
Oct. 17 '12 at 16:39
source share

I had a problem with the UIPageViewController crashing with iOS6 with the same error ("The number of view controllers provided (0) does not match the required number (1) for the requested transition").

None of the above solutions worked for me, but in the end I found that moving the next line from viewDidLoad to viewDidAppear fixed.

 self.view.gestureRecognizers = self.pageViewController.gestureRecognizers; 
+1
Nov 19 '12 at 17:18
source share

In general, the problem is here.

What I did was a fix that only returns the clone before / afterViewController instead of nil, i.e.

 // viewController = before/afterViewController NSUInteger index = [self indexOfViewController:viewController]; // NOTE: return nil crashes in iOS6 return [self viewControllerAtIndex:index storyboard:viewController.storyboard]; 

This means that you can twist the pages forever, but I had no other choice ... The best solution is always welcome.

-one
Sep 24 '12 at 16:39
source share



All Articles