这只是在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月并尝试返回
返回nil。
该应用程序将崩溃。
ios5没有发生这种情况。我需要将gestureRecognizer委托分配给我的viewController,因为我并不总是希望pageViewController处理触摸事件。
还有其他人经历过这个或指出我是否做错了什么?
非常感谢 斯图尔特。
答案 0 :(得分:8)
终于找到了解决我问题的办法,这让我感到悲痛,所以希望这可以帮助别人。
问题是如果将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;
}
}
然后从
返回nilpageViewController:viewControllerAfterViewController:
会崩溃!仅限iOS6 !!
我的问题是我需要设置gestureRecognisers的委托,因为我需要在某些情况下拦截panGesture,即由于那里的某些按钮而不允许用户翻页,因为触摸了某些部分。
解决方案是从
中提取逻辑pageViewController:viewControllerAfterViewController:
进入
gestureRecognizer:shouldReceiveTouch:
因为只要我们从那里返回NO,它就不会继续打电话
pageViewController:viewControllerAfterViewController:
所以不需要返回nil并且崩溃。
但是,这在序列的第一页和最后一页上不起作用。例如,在第一页上,您希望允许页面向前但不向后。所以我想看看传入的GestureRecogniser,将其投射到PanGesture,然后检查速度,如果速度表示转回(>> 0.0f),则返回NO。听起来不错,但速度始终为零。
然后我在GestureRecognizer委托上找到了一个非常有用的小函数:
gestureRecognizerShouldBegin:gestureRecognizer
在
之后调用此函数gestureRecognizer:shouldReceiveTouch:
但是这次手势的速度与我预期的一样,所以我可以检查速度,如果是>则只返回第一页的YES。 0.0F
答案 1 :(得分:7)
我相信我找到的解决方案比重构任何现有的pageViewController代码要复杂得多,如noRema所提到的,或者如同here那样搞乱选择器转发,尽管我没有找到它那些解决方案作为参考。
只需稍作调整即可轻松进入任何UIPageViewController项目。
要实现,请按原样保留代码;所有现有逻辑应保持不变,因为这只会影响UIGestureRecognizer Delegate行为。覆盖手势委托方法 - (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;
}
答案 2 :(得分:4)
在iOS 6下的UIPageViewController中调查Pan Gesture的问题时,我注意到它可以在一个手势中多次在视图控制器方法之前/之后调用。这在我的特定情况下是不好的,因为我需要等到动画完成每页翻页才能导航到下一页/上一页。 因此,我们的方法具有这样的结构:
- (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
方法相同。
动画结束后,调用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
状态的情况下,我们尝试添加逻辑以在控制器方法之前/之后不调用(基于某些测试来调查它以确定在循环中调用方法时的手势状态)。 p>
添加如下方法:
- (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标志的循环问题。
希望这会对某人有所帮助。
答案 3 :(得分:2)
我遇到了同样的问题,UIPageViewController与iOS6崩溃时导航超出界限时出现相同的错误。
以上解决方案均不适合我,但我最终发现将以下行从viewDidLoad
移至viewDidAppear
完全修复了此问题。
self.view.gestureRecognizers = self.pageViewController.gestureRecognizers;