在ios6中,将您的pageViewController的gestureRecognizers委托设置为viewController会导致崩溃

这只是开始发生与ios6,但如果您启动一个新的项目使用页面视图控制器模板。 然后进来

PCRootViewControlle::viewDidLoad() 

将这些行添加到方法的底部。

 for (UIGestureRecognizer *gR in self.pageViewController.gestureRecognizers) { gR.delegate = self; } 

您将需要分配viewController,以便它符合UIGestureRecognizerDelegate并实现该方法

 -(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch (UITouch *)touch { return YES; } 

现在,如果你运行该应用程序,并尝试将页面超出界限,即去1月,并尝试返回

  • (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController

返回零。

该应用程序将崩溃。

这并没有发生与ios5。 我需要将gestureRecognizer委托分配给我的viewController,因为我不总是希望pageViewController处理触摸事件。

有没有经历过这个或指出如果我做错了什么?

许多感谢斯图尔特。

终于find了解决我的问题,这让我很悲伤,所以希望这可以帮助别人。

问题是如果你设置pageViewControllers委托给你的viewController

 for (UIGestureRecognizer *gR in self.pageController.view.gestureRecognizers) { if ([gR isKindOfClass:[UITapGestureRecognizer class]]) { gR.enabled = NO; } else if ([gR isKindOfClass:[UIPanGestureRecognizer class]]) { gR.delegate = self; } } 

然后返回零

 pageViewController:viewControllerAfterViewController: 

会崩溃! 只在iOS6!

我的问题是,我需要设置gestureRecognisers的代表,因为我需要在某些情况下截取panGesture,即不允许用户翻页,因为有一些button触摸它的某些部分。

解决的办法是把逻辑从

 pageViewController:viewControllerAfterViewController: 

 gestureRecognizer:shouldReceiveTouch: 

因为只要我们从这个返回NO,那么它不会继续打电话

 pageViewController:viewControllerAfterViewController: 

所以不需要返回零,并得到一个崩溃。

但是,这在序列中的第一页和最后一页不起作用。 例如,在第一页上,您希望允许该页面向前但不能返回。 所以我想着看看传入的GestureRecogniser,将它转换成PanGesture,然后检查速度,如果速度表示返回(> 0.0f)然后返回NO。 这听起来不错,但速度总是为零。

然后,我在GestureRecognizer委托中find了一个非常有用的小函数:

 gestureRecognizerShouldBegin:gestureRecognizer 

这个函数被调用之后

 gestureRecognizer:shouldReceiveTouch: 

但这一次手势的速度是我所期望的,所以我可以检查速度,只有返回YES为第一页,如果它是> 0.0f

我相信我已经find了一个解决scheme,比重构任何现有的pageViewController代码,像noRema提到的那样麻烦,或者像这里提到的那样混淆了select器转发,尽pipe如果没有这两个解决scheme作为参考,我永远也找不到。

这应该只需稍作调整即可轻松放入任何UIPageViewController项目。

为了实现,你保留你的代码原样; 所有现有的逻辑应该保持不变,只会影响UIGestureRecognizer委托行为。 覆盖手势委托方法 – (BOOL)gestureRecognizerShouldBegin:类似下面的东西:

注意:我使用Apple的基于页面的应用程序代码作为起点,所以请参阅如果术语_modelController_pageViewController导致任何混淆。

 - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer { //Make sure we're not trying to turn backward past the first page: if ([_modelController indexOfViewController:[_pageViewController.viewControllers objectAtIndex:0]] == 0) { if ([(UIPanGestureRecognizer*)gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] && [(UIPanGestureRecognizer*)gestureRecognizer velocityInView:gestureRecognizer.view].x > 0.0f) { NSLog(@"DENIED SWIPE PREVIOUS ON FIRST PAGE"); return NO; } if ([(UITapGestureRecognizer*)gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]] && [(UITapGestureRecognizer*)gestureRecognizer locationInView:gestureRecognizer.view].x < self.view.frame.size.width/2) { NSLog(@"DENIED TAP PREVIOUS ON FIRST PAGE"); return NO; } } //Make sure we're not trying to turn forward past the last page: int finalVCindexSubtractor; if (UIInterfaceOrientationIsLandscape(self.interfaceOrientation)) { // the vc we compare is a different distance from the end based on our orientation: finalVCindexSubtractor = 2; } else { finalVCindexSubtractor = 1; } if ([_modelController indexOfViewController:[_pageViewController.viewControllers objectAtIndex:0]] == _modelController.pageData.count-finalVCindexSubtractor) { if ([(UIPanGestureRecognizer*)gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] && [(UIPanGestureRecognizer*)gestureRecognizer velocityInView:gestureRecognizer.view].x < 0.0f) { NSLog(@"DENIED SWIPE NEXT ON LAST PAGE"); return NO; } if ([(UITapGestureRecognizer*)gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]] && [(UITapGestureRecognizer*)gestureRecognizer locationInView:gestureRecognizer.view].x > self.view.frame.size.width/2) { NSLog(@"DENIED TAP NEXT ON LAST PAGE"); return NO; } } return YES; } 

当在iOS 6下调查UIPageViewController中的Pan Gesture问题时,我注意到它可以在一个手势中多次调用视图控制器方法之前/之后。 这在我的情况下是不好的,因为我需要等到每个页面的animation完成后才能够导航到下一个/上一个页面。 因此我们的方法有这样的结构:

 - (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController { if (animationInProgress) return nil; UIViewController *result = nil; //do stuff to init result controller for next/prev page if (result) animationInProgress = YES; return result; } 

viewControllerAfterViewController方法相同。

animation结束后,调用UIPageViewControllerDelegate的这个方法:

 - (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed { animationInProgress = NO; //do other stuff to handle finishing animation. } 

由于PanGesture被多次调用,因此viewControllerAfterViewController和另外一个方法被调用了几次,不幸的是didFinishAnimating方法在这种情况下没有被调用,这导致animationInProgress标志总是被设置为YES并且用户无法通过所有。 注:只发生在iOS 6。

要解决这个问题,我们必须以某种方式处理PanGesture。 使用UIView gestureRecognizerShouldBegin:gestureRecognizer (它是在iOS 6中添加的)根本没有解决问题,将控制器设置为委托的手势导致崩溃时,方法之前/之后返回nil。 因此,我们试图在PanGesture处于UIGestureRecognizerStateChanged状态(基于某些testing以确定在循环中调用方法时确定什么是手势状态)的情况下,尝试添加逻辑以在控制器方法之前/之后不调用控制器方法。

通过添加如下方法:

 - (BOOL)skipIfPanGestureInProgress { BOOL shouldSkip = NO; if(pvcPanGestureRecognizer && [pvcPanGestureRecognizer state] == UIGestureRecognizerStateChanged){ animationInProgress = NO; shouldSkip = YES; } return shouldSkip; } 

之后,方法如下所示:

 - (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController { if([self skipIfPanGestureInProgress]){ return nil; } if (animationInProgress) return nil; UIViewController *result = nil; //do stuff to init result controller for next/prev page if (result) animationInProgress = YES; return result; } 

这有助于解决animationInProgress标志的循环问题。

希望这会对某人有所帮助。

我遇到同样的问题与UIPageViewController与iOS6崩溃时导航超越界限相同的错误。

上述解决scheme都没有为我工作,但我最终发现,将下面的行从viewDidLoad移到viewDidAppear完全解决它。

 self.view.gestureRecognizers = self.pageViewController.gestureRecognizers;