点击状态栏时,UIPageViewController可防止我的表格视图滚动到顶部

时间:2014-01-09 23:18:23

标签: ios objective-c uitableview uisearchdisplaycontroller uipageviewcontroller

我在发布此问题之前进行了搜索,但找不到任何内容。

我有一个很大的问题。我有一个滚动类型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];
}

5 个答案:

答案 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

相关问题