最近写了一个阅读器App,产品要求阅读页使用仿真翻页模式,我使用了苹果提供的UIPageViewController的仿真翻页模式,没有想到系统的也有坑。遇到的坑都是跟用户快速翻页有关。
坑一:快速翻页出现闪退
当快速翻阅的时候,出现下面的闪退日志
Received CA callback for state, but active state queue is empty'
(
0 CoreFoundation 0x000000010780df45 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x000000010a81cdeb objc_exception_throw + 48
2 CoreFoundation 0x000000010780ddaa +[NSException raise:format:arguments:] + 106
3 Foundation 0x0000000107f5a5ee -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 198
4 UIKit 0x000000010911a5c7 -[_UIPageCurl _pageCurlAnimationDidStop:withState:] + 473
5 UIKit 0x00000001091146d1 -[_UIPageCurlState animationDidStop:finished:] + 106
6 QuartzCore 0x000000010b248fa0 _ZN2CA5Layer23run_animation_callbacksEPv + 308
7 libdispatch.dylib 0x000000010b38e49b _dispatch_client_callout + 8
8 libdispatch.dylib 0x000000010b3762af _dispatch_main_queue_callback_4CF + 1738
9 CoreFoundation 0x000000010776e2e9 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
10 CoreFoundation 0x000000010772f8a9 __CFRunLoopRun + 2073
11 CoreFoundation 0x000000010772ee08 CFRunLoopRunSpecific + 488
12 GraphicsServices 0x000000010cb08ad2 GSEventRunModal + 161
13 UIKit 0x00000001089c230d UIApplicationMain + 171
14 ??á????à? 0x0000000105afd32f main + 111
15 libdyld.dylib 0x000000010a17e92d start + 1
16 ??? 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminate_handler unexpectedly threw an exception
当修改了取出设置当前阅读页的动画时,在一定程度上缓解了闪退的出现,代码如下:
[_pageViewController setViewControllers:@[[self readViewWithPage:_currentPage]] direction:UIPageViewControllerNavigationDirectionReverse animated:NO completion:nil];
你可能还会遇到其他关于动画或者内存闪退的日志,都可以这样处理。
坑二:快速左右翻页出现页面错乱
我的应用中有遇到一个这样的bug,当你快速向前翻页然后又快速向后翻页,就会出现向前翻的某一页一直出现的现象,继续操作,会出现你想不到的bug现象。这是苹果控件本身缓存的一个bug,研究了很久,没有更好的办法,想到的只是让用户翻页速度可控,就是控制用户的点击速度,思路就像大家经常会用到的不让按钮连续点击一样,或者是控制在连续点击时间间隔为一个固定的数值,比如1秒内点击一次,等等。
我的代码处理如下:
#pragma mark - UIPageViewController DataSource
- (nullableUIViewController*)pageViewController:(UIPageViewController*)pageViewController viewControllerBeforeViewController:(UIViewController*)viewController {
WeakSelf
_pageViewController.view.userInteractionEnabled = NO;//限制UIPageViewController上的手势事件
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
weakSelf.pageViewController.view.userInteractionEnabled = YES;//恢复UIPageViewController上的手势事件
});
..........
}
- (nullableUIViewController*)pageViewController:(UIPageViewController*)pageViewController viewControllerAfterViewController:(UIViewController*)viewController {
WeakSelf
_pageViewController.view.userInteractionEnabled = NO;//限制UIPageViewController上的手势事件
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5* NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
weakSelf.pageViewController.view.userInteractionEnabled = YES;//恢复UIPageViewController上的手势事件
});
..........
}
上面代码的处理效果是实现0.5内允许用户翻页一次,这样就避免了用户翻页过快,也就避免了翻页过快带来的一系列异常的现象。
如果有大神有更好的处理方法,解决这个bug也烦请留言,大家共同探讨,共同学习~