【问题标题】:UIPageViewController in iOS6iOS6 中的 UIPageViewController
【发布时间】:2012-09-24 12:51:34
【问题描述】:

在 iOS6 的 viewControllerAfterViewControllerviewControllerBeforeViewController 方法中,如果我返回 nil(当我在第一页或最后一页时阻止页面导航),应用程序会因此而崩溃例外:

'提供的视图控制器数量 (0) 与请求的转换所需的数量 (1) 不匹配'

在 iOS5 中一切正常。

【问题讨论】:

  • 有趣的是,此页面上的所有解决方案均不涉及 UIPageViewControllerdoubleSided 属性。这对我来说是个问题……或者其中之一。

标签: iphone ios objective-c uipageviewcontroller


【解决方案1】:

我有同样的问题。我发现原因是替换 UIPageViewController 的 UIPanGestureRecognizer 上的委托,这真的是不行。平移手势识别器正在调用一个未记录的方法 _gestureRecognizerShouldBegin:(注意前导下划线),UIPageViewController 实现并显然依赖于它才能正常工作(阅读:不崩溃)。我最终在我的类中实现了 respondsToSelector: 和 forwardingTargetForSelector: ,它使用 UIPageViewController 将未记录的委托方法传递给 UIPageViewController 而不具体命名它(并且几乎肯定会为我赢得应用商店审查拒绝)。

-(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;
}

我的长期解决方案是重新使用 UIPageViewController,这样我就不需要替换手势识别器代理了。

【讨论】:

  • +1。我最终没有替换 panGestureRecognizer.delegate 作为我的 viewController。
  • 所以...我不明白。这个解决方案会让你的应用被拒绝吗?所以也许更好地接受@puneeth 的建议?
  • 这会被苹果拒绝吗?
  • itux.idev.pro/2012/12/… ... 使用两个 uiviewcontroller,动态加载页面,您的修复也节省了我的时间。非常感谢,相信 Apple 并没有拒绝我们的应用 :)
【解决方案2】:

啊,想知道为什么没有人指出这个错误,我花了将近 2 个晚上才找到解决方案。

OLD CODE(iOS 5.1) :当在第一页和最后一页返回 nil 时,您会遇到应用程序崩溃。它在 iOS 5.1 中可以正常工作,但在 iOS 6 中不会。

- (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) : 将手势效果添加到超级视图后,只需调用名为 -(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer 的委托。我所做的很简单,计算用户翻动第一页和最后一页的速度(我的意思是使用手势识别器),我拒绝滑动。您只需粘贴以下代码,您就完成了!.

- (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];
}

【讨论】:

  • 这似乎对我来说效果最好,除了我使用了大于 0.0 的速度阈值,因为该错误似乎与非常快速的平移电影有关。
【解决方案3】:

这已经得到了很好的讨论,但我还有一件事要补充。考虑为什么您将手势识别器的委托设置为 self。就我而言,这是因为在某些情况下,我想阻止手势识别器识别,代表的gestureRecognizerShouldBegin:

但在出现此问题的 iOS 6 中,通过在 UIView 上实现 gestureRecognizerShouldBegin:,有一种全新的方法可以做到这一点。 (这是 iOS 6 中新增的 UIView 实例方法。)

因此,我能够完全完成我之前完成的工作,而无需更改手势识别器的委托。

【讨论】:

  • 这是最好的答案。但是,文档本身省略了 UIView.h 标头中提到的细节:“当识别器尝试过渡到 UIGestureRecognizerStatePossible 时调用,如果由于手势识别而取消对该视图的触摸命中测试”。这意味着您必须将触摸被测试的视图子类化,否则您可能不会;就我而言,我必须继承 UISlider 才能实现此方法。
【解决方案4】:

我遇到了 UIPageViewController 与 iOS6 崩溃并出现相同错误的问题(“提供的视图控制器的数量 (0) 与请求的转换所需的数量 (1) 不匹配”)。

上述解决方案都不适合我,但我最终发现将以下行从 viewDidLoad 移动到 viewDidAppear 修复了它。

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

【讨论】:

  • 这并没有为我消除崩溃。
【解决方案5】:

这里的问题完全一样。

我所做的是一个修补程序,它只是返回 before/afterViewController 的克隆而不是 nil,即

// viewController = before/afterViewController
NSUInteger index = [self indexOfViewController:viewController];

// NOTE: return nil crashes in iOS6
return [self viewControllerAtIndex:index storyboard:viewController.storyboard];

这意味着你可以永远翻页,但我别无选择...... 更好的解决方案总是受欢迎的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多