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]; }
One way to do this is programmatically create an UIScrollView in your UIViewController . To control the scrollability you can set the ScrollView contentSize property.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With