Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIPageViewController prevents my table view from scrolling to top when tapping the status bar

Tags:

I searched before posting this question, but couldn't find anything.

I'm having a huge issue. I have a scrolling type UIPageViewController as the basis of my app, with 3 view controllers.

One of the view controller's (listTableView) has a table view and a search display controller.

The problem is, I cannot scroll to the top of the table view when tapping on the status bar like a normal table view. I believe the UIPageViewController is interfering with this, but I have no idea how to go about fixing it, but I know that I need to for my app to not feel broken.

I appreciate any help offered.

I know someone will ask for code even though it's irrelvant in this case but here it is for creating the 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]; } 
like image 918
klcjr89 Avatar asked Jan 09 '14 23:01

klcjr89


People also ask

How to make a view controller scrollable?

One way to do this is programmatically create an UIScrollView in your UIViewController . To control the scrollability you can set the ScrollView contentSize property.

What is Ui scroll view?

UIScrollView is the superclass of several UIKit classes, including UITableView and UITextView . A scroll view is a view with an origin that's adjustable over the content view. It clips the content to its frame, which generally (but not necessarily) coincides with that of the app's main window.


1 Answers

Solution

After chat, we discovered something interesting. The page view controller keeps other view controllers' views inside the view hierarchy, so they also capture the scrollsToTop behavior and interfere. This means that you need to disable scrollsToTop for each scrollable view inside viewWillDisappear: of the disappearing view controllers (and enable again on viewWillAppear:).


Original Investigation

The quick and easy way: The scrollview is the only subview of the UIPageViewController's view:

self.pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil]; 

Inspecting in debugger:

(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>> 

You could use several methods to reach that scrollview. Easiest is to iterate self.pageViewController.view.subviews and find the one that is a subclass of UIScrollView. Since it is the only subview, your loop will end after one iteration.

Is this solution optimal? No. Is it error prone? In theory, sure. Is it likely to change? Not likely, as the view hierarchy is pretty logical. It at least gives you a quick fix, instead of having to deal with changing the entire app structure due to a small oversight by Apple (providing the user with access to the scrollview).

You should open a feature request with Apple over at https://bugreport.apple.com.

like image 93
Léo Natan Avatar answered Oct 27 '22 23:10

Léo Natan