我在发布此问题之前进行了搜索,但找不到任何内容。
我有一个很大的问题。我有一个滚动类型UIPageViewController作为我的应用程序的基础,有3个视图控制器。
其中一个视图控制器(listTableView)有一个表视图和一个搜索显示控制器。
问题是,当像状态表视图一样点击状态栏时,我无法滚动到表格视图的顶部。我相信UIPageViewController正在干扰这一点,但我不知道如何修复它,但我知道我需要让我的应用程序不会感到不适。
感谢您提供的任何帮助。
我知道有人会要求代码,即使在这种情况下它是无关紧要的,但这里是用于创建UIPageViewController:
#import "MainViewController.h"
@interface MainViewController ()
@property (nonatomic, strong) UIPageViewController *pageViewController;
@property (nonatomic, strong) NSArray *contentViewControllers;
@end
@implementation MainViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.pageViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"PageView"];
self.pageViewController.dataSource = self;
UIViewController *settings = [self.storyboard instantiateViewControllerWithIdentifier:@"Settings"];
UIViewController *listTableView = [self.storyboard instantiateViewControllerWithIdentifier:@"List"];
UIViewController *first = [self.storyboard instantiateViewControllerWithIdentifier:@"First"];
self.contentViewControllers = [NSArray arrayWithObjects:settings,listTableView,first,nil];
[self.pageViewController setViewControllers:@[first] direction:UIPageViewControllerNavigationDirectionReverse animated:NO completion:nil];
[self addChildViewController:self.pageViewController];
[self.view addSubview:self.pageViewController.view];
[self.pageViewController didMoveToParentViewController:self];
self.view.backgroundColor = [UIColor colorWithRed:(248.0/255.0) green:(248.0/255.0) blue:(248.0/255.0) alpha:1.0];
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController
viewControllerBeforeViewController:(UIViewController *)viewController {
NSUInteger index = [self.contentViewControllers indexOfObject:viewController];
if (index == 0) {
return nil;
}
return self.contentViewControllers[index - 1];
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController
viewControllerAfterViewController:(UIViewController *)viewController {
NSUInteger index = [self.contentViewControllers indexOfObject:viewController];
if (index >= self.contentViewControllers.count - 1) {
return nil;
}
return self.contentViewControllers[index + 1];
}
答案 0 :(得分:30)
解决方案
聊天后,我们发现了一些有趣的东西。页面视图控制器将其他视图控制器的视图保留在视图层次结构中,因此它们还捕获scrollsToTop
行为并进行干扰。这意味着您需要为消失的视图控制器的scrollsToTop
内的每个可滚动视图禁用viewWillDisappear:
(并在viewWillAppear:
上再次启用)。
原始调查
快速简便的方法:scrollview是UIPageViewController
视图的唯一子视图:
self.pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
在调试器中检查:
(lldb) po [self.pageViewController.view recursiveDescription]
<_UIPageViewControllerContentView: 0x8d7c390; frame = (0 0; 320 480); clipsToBounds = YES; opaque = NO; autoresize = W+H; layer = <CALayer: 0x8d7c4a0>>
| <_UIQueuingScrollView: 0xa912800; frame = (0 0; 320 480); clipsToBounds = YES; gestureRecognizers = <NSArray: 0x8d7cc90>; layer = <CALayer: 0x8d7c7e0>; contentOffset: {320, 0}>
| | <UIView: 0x8d7da00; frame = (0 0; 320 480); layer = <CALayer: 0x8d7da60>>
| | <UIView: 0x8d7dab0; frame = (320 0; 320 480); layer = <CALayer: 0x8d7db10>>
| | <UIView: 0x8d7db40; frame = (640 0; 320 480); layer = <CALayer: 0x8d7dba0>>
您可以使用多种方法来覆盖该滚动视图。最简单的方法是迭代self.pageViewController.view.subviews
并找到UIScrollView
的子类。由于它是唯一的子视图,因此循环将在一次迭代后结束。
此解决方案是否最佳?不。它容易出错吗?理论上,当然。它有可能改变吗?不太可能,因为视图层次结构非常合乎逻辑。它至少可以为您提供快速解决方案,而不必由于Apple的小疏忽(允许用户访问滚动视图)来处理更改整个应用程序结构。
您应该在https://bugreport.apple.com处与Apple打开功能请求。
答案 1 :(得分:3)
-scrollToTop
上的iOS 7文档说
在iPhone上,如果有更多内容,滚动到顶部的手势无效 一个滚动视图在屏幕上,其中scrollsToTop设置为YES。
我正在以类似的方式使用UIPageViewController;我的一个页面控制器是一个UITableViewController。所以我被two-scrollviews-onscreen-no-scrolltotop
政策所打动。
Kyle通过隐形按钮实现自己的scrollToTop行为的想法可能是您在这种情况下最可靠的选择。
答案 2 :(得分:1)
在我的情况下,我在UITableView
的子视图控制器中有一个UIPageViewController
。从Leo Natan的建议中提取,将其添加到我的孩子视图控制器中完成了这项工作:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.tableView.scrollsToTop = YES;
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
self.tableView.scrollsToTop = NO;
}
如上所述,子视图控制器中的竞争UIScrollView
将干扰彼此的scrollsToTop委托方法。此代码确保其中只有一个一次启用了scrollsToTop。
答案 3 :(得分:1)
我用过这个:
for v in view.subviews {
if v.isKindOfClass(UIScrollView) {
(v as! UIScrollView).scrollsToTop = false
}
}
但是,如果还有其他滚动视图可以滚动到顶部,那么你的工作就会胜利。使用此脚本查找其他滚动视图: {{3}},然后将其滚动停用到顶部。
然后在想要滚动到顶部工作的viewcontroller中,添加以下内容:
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
tableView.scrollsToTop = true
}
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
tableView.scrollsToTop = false
}
答案 4 :(得分:0)
我认为最好的解决方案是使用UIPageViewControllerDelegate协议的以下两种方法(快速和脏版本,考虑到屏幕上只有一个视图控制器):
- (void)pageViewController:(UIPageViewController *)pageViewController willTransitionToViewControllers:(NSArray *)pendingViewControllers
{
((UITableViewController *)pendingViewControllers[0].tableView).scrollsToTop = YES;
}
- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed
{
((UITableViewController *)previousViewControllers[0].tableView).scrollsToTop = NO;
}
编辑:更好地使用已接受答案的approach outlined in the last paragraph