UIPageViewController上下滑动页面重复Bug解决方案

Posted by zhouen on 2018-10-12

UIPageViewController实现小说阅读器遇到的bug及解决方案

上下滑动引起页面重复的bug

开始时的思路:修改UIPageViewController的UIPanGestureRecognizer手势

以下方案引发了以下bug

The number of view controllers provided (0) doesn’t match the number required (2) for the requested transition

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
解决方案开始思路:修改UIPageViewController的UIPanGestureRecognizer手势

//1 修改UIPageViewController的UIPanGestureRecognizer手势代理
for (UIGestureRecognizer *gr in _pageViewController.gestureRecognizers) {
if ([gr isKindOfClass:[UIPanGestureRecognizer class]]) {

gr.delegate = self;
}
}

//实现代理方法
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {

//可如下方式过滤手势
// if ([touch.view isDescendantOfView:self.topView] ||
// [touch.view isDescendantOfView:self.bottomView] ||
// [touch.view isDescendantOfView:self.settingView] ) {
// return NO;
// }


if ([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]) {

UIPanGestureRecognizer *swipe = (UIPanGestureRecognizer *)gestureRecognizer;
if (gestureRecognizer.state == UIGestureRecognizerStateChanged) {
return [self commitTranslation:[swipe translationInView:self.view]];
}
}
return YES;
}

//判断滑动方向
- (BOOL)commitTranslation:(CGPoint)translation {
CGFloat absX = fabs(translation.x);
CGFloat absY = fabs(translation.y);

// 设置滑动有效距离
if (MAX(absX, absY) < 20)
return NO;


if (absX > absY ) {

if (translation.x < 0) {
//向左滑动
}else{
//向右滑动
}

return YES;

} else if (absY > absX) {
if (translation.y<0) {

//向上滑动
}else{

//向下滑动
}
return NO;
}

return YES;

}

解决方案二

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController {
//此处会修正为正确的index
NSUInteger index = [self indexOfViewController:(ContentViewController *)viewController];
if (index == NSNotFound) {
return nil;
}
index++;
if (index == [self.pageContentArray count]) {
return nil;
}
return [self viewControllerAtIndex:index];


}

- (NSUInteger)indexOfViewController:(ContentViewController *)viewController {
return [self.pageContentArray indexOfObject:viewController.content];
}

快速滑动 及其 滑动未完成又返回引起的问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#pragma mark - UIPageViewControllerDataSource
//显示前一页
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController {
if (self.transiting) { return nil; }
return vc;
}

//显示下一页
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController {
if (self.transiting) { return nil; }

return vc;
}

- (void)pageViewController:(UIPageViewController *)pageViewController willTransitionToViewControllers:(NSArray<UIViewController *> *)pendingViewControllers {
//防止快速滑动引起的问题
self.transiting = YES;
}

- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray<UIViewController *> *)previousViewControllers transitionCompleted:(BOOL)completed {
self.transiting = NO;

if (!completed) {
修改页面索引为未完成时的索引

}
}