在 iOS6 中的 viewControllerAfterViewController 和 viewControllerBeforeViewController 方法中,如果我返回 nil(当我在第一页或最后一页时阻止页面导航),应用程序崩溃并出现以下异常:
'提供的视图控制器数量 (0) 与请求的转换所需的数量 (1) 不匹配'
在 iOS5 中一切正常。
在 iOS6 中的 viewControllerAfterViewController 和 viewControllerBeforeViewController 方法中,如果我返回 nil(当我在第一页或最后一页时阻止页面导航),应用程序崩溃并出现以下异常:
'提供的视图控制器数量 (0) 与请求的转换所需的数量 (1) 不匹配'
在 iOS5 中一切正常。
我遇到过同样的问题。我发现原因是替换 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,这样我就不需要替换手势识别器代表了。
啊,想知道为什么没有人指出这个错误,我花了将近 2 个晚上才找到解决方案。
旧代码(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];
}
这已经得到了很好的讨论,但我还有一件事要补充。考虑一下为什么要将手势识别器的委托设置为 self。就我而言,这是因为在某些情况下,我想阻止手势识别器识别,代表的gestureRecognizerShouldBegin:
.
gestureRecognizerShouldBegin:
但是在出现这个问题的 iOS 6 中,通过在 UIView 上实现,有一种全新的方法可以做到这一点。(这是 iOS 6 中新增的 UIView 实例方法。)
因此,我能够完全完成我之前完成的工作,而无需更改手势识别器的委托。
我遇到了 UIPageViewController 与 iOS6 崩溃并出现相同错误的问题(“提供的视图控制器的数量 (0) 与请求的转换所需的数量 (1) 不匹配”)。
上述解决方案都不适合我,但我最终发现将以下行从移动viewDidLoad
到viewDidAppear
修复它。
self.view.gestureRecognizers = self.pageViewController.gestureRecognizers;
这里完全一样的问题。
我所做的是一个修补程序,它只是返回 before/afterViewController 的克隆而不是 nil,即
// viewController = before/afterViewController
NSUInteger index = [self indexOfViewController:viewController];
// NOTE: return nil crashes in iOS6
return [self viewControllerAtIndex:index storyboard:viewController.storyboard];
这意味着您可以永远翻页,但我别无选择......总是欢迎更好的解决方案。