1

I did search first, and have seen somewhat similar issues, but no definitive answer on how to solve it. The problem I'm having with my app is that I have 3 navigation controllers that are added as child view controllers into a UIScrollView. I originally wanted to use a UIPageViewController instead, but that turned out to be a mess since you can't disable the bouncing on it. For each navigation controller, a tableView controller is embedded within it in storyboard.

viewDidAppear and viewDidDisappear are not called for my child view controllers because their views are added as subviews to the paging scroll view at runtime, and I kindof believe is why I can't figure out how to solve this.

I need each of my table view controller's to respond to the user touching the status bar for the respective tableView to scroll to the top.

Here is the code I'm using for the setup of the app's main scroll view and adding the 3 view controller's views to it:

I appreciate any help offered!

MainViewController.h

#import <UIKit/UIKit.h>

@interface MainViewController : UIViewController <UIScrollViewDelegate>

@end

MainViewController.m:

#import "MainViewController.h"

@interface MainViewController ()

@property (nonatomic, strong) UINavigationController *settings;
@property (nonatomic, strong) UINavigationController *hehTwo;
@property (nonatomic, strong) UINavigationController *hehOne;
@property (nonatomic, strong) IBOutlet UIScrollView *scrollView;

@end

@implementation MainViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.settings = [self.storyboard instantiateViewControllerWithIdentifier:@"Settings"];

    self.hehTwo = [self.storyboard instantiateViewControllerWithIdentifier:@"HehTwo"];

    self.hehOne = [self.storyboard instantiateViewControllerWithIdentifier:@"HehOne"];

    [self addChildViewController:self.settings];
    [self addChildViewController:self.hehTwo];
    [self addChildViewController:self.hehOne];

    CGRect hehTwoFrame = self.hehTwo.view.frame;
    hehTwoFrame.origin.x = 320;
    self.hehTwo.view.frame = hehTwoFrame;

    CGRect hehOneFrame = self.hehOne.view.frame;
    hehOneFrame.origin.x = 640;
    self.hehOne.view.frame = hehOneFrame;

    [self.scrollView addSubview:self.settings.view];

    [self.scrollView addSubview:self.hehTwo.view];

    [self.scrollView addSubview:self.hehOne.view];

    // Setting offset so the farthest right controller is heh One
    [self.scrollView setContentOffset:CGPointMake(640,0)];

    self.scrollView.delegate = self;

    self.scrollView.bounces = NO;

    self.scrollView.delaysContentTouches = NO;

    self.scrollView.contentSize = CGSizeMake(960, self.view.frame.size.height);

    self.scrollView.scrollsToTop = NO;
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    CGFloat width = scrollView.frame.size.width;
    NSInteger page = (scrollView.contentOffset.x + (0.5f * width)) / width;

    if (page == 0)
    {
        // Settings
    }
    else if (page == 1)
    {
        // Heh Two
    }
    else
    {
        // Heh One
    }
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
}

@end
klcjr89
  • 5,862
  • 10
  • 58
  • 91

1 Answers1

3

First of all, you need to set self.tableView.scrollsToTop = NO; on HehTwo and HehOne (if these two are initially hidden) in their viewDidLoad implementation.

And now, update this method:

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    CGFloat width = scrollView.frame.size.width;
    NSInteger page = (scrollView.contentOffset.x + (0.5f * width)) / width;

    if (page == 0)
    {
        // Settings

        ((UITableViewController *)self.settings.viewControllers[0]).tableView.scrollsToTop = YES;
        ((UITableViewController *)self.hehOne.viewControllers[0]).tableView.scrollsToTop = NO;
        ((UITableViewController *)self.hehTwo.viewControllers[0]).tableView.scrollsToTop = NO;
    }
    else if (page == 1)
    {
        // Heh Two

        ((UITableViewController *)self.settings.viewControllers[0]).tableView.scrollsToTop = NO;
        ((UITableViewController *)self.hehOne.viewControllers[0]).tableView.scrollsToTop = NO;
        ((UITableViewController *)self.hehTwo.viewControllers[0]).tableView.scrollsToTop = YES;
    }
    else
    {
        // Heh One

        ((UITableViewController *)self.settings.viewControllers[0]).tableView.scrollsToTop = NO;
        ((UITableViewController *)self.hehOne.viewControllers[0]).tableView.scrollsToTop = YES;
        ((UITableViewController *)self.hehTwo.viewControllers[0]).tableView.scrollsToTop = NO;
    }
}

That's all! This should fix it.

arturgrigor
  • 9,361
  • 4
  • 31
  • 31
  • I'll let you know later this evening, I did try setting the tableView's scrolls to top before programmatically, and it didnt work, but I also didnt have the other implementation you've provided me. – klcjr89 Jan 23 '14 at 03:07
  • Well, it seems that you have more scroll views than these 4 (the initial scroll view plus those 3 table views). – arturgrigor Jan 23 '14 at 03:35
  • I just put an NSLog in to verify that my Settings view scrolls to top "should be" scrolling to the top and it returns yes, so you may be on to something. How can i find all the interfering scroll views? – klcjr89 Jan 23 '14 at 03:37
  • The thing is that only one scroll view from the current view controller should have scrollsToTop = YES and it seems that you didn't set all of them to NO besides the only tableView that you want it to scroll to top. – arturgrigor Jan 23 '14 at 03:37
  • But I have all of my table view controllers set to scrollsToTop to NO on their view did load – klcjr89 Jan 23 '14 at 03:42
  • Take a look at this answer and use that method to check all the sub views from the view controller that has these 3 child view controllers. http://stackoverflow.com/questions/7243888/how-to-list-out-all-the-subviews-in-a-uiviewcontroller-in-ios – arturgrigor Jan 23 '14 at 03:45
  • See if you have more than one sub view that has scrollsToTop set to YES. – arturgrigor Jan 23 '14 at 03:46
  • How would i contstruct such a method to check all the subviews in the app window? – klcjr89 Jan 23 '14 at 03:47
  • You only need to check for the current presented view controller. So you can call the method with self.scrollView as the param. – arturgrigor Jan 23 '14 at 03:51
  • What in the world, I found this out: 2014-01-22 22:51:28.752[1741:70b] scrollsToTop = YES! 2014-01-22 22:51:2 – klcjr89 Jan 23 '14 at 03:52
  • Well, set it to NO :) – arturgrigor Jan 23 '14 at 03:53
  • I dont know where that view is coming from though? I do have a UICollectionViewController but its completely empty and not even loaded at run time – klcjr89 Jan 23 '14 at 03:54
  • Track down it's superviews by going from one superview to another, just as you're doing with the sub views and you'll figure it out :) – arturgrigor Jan 23 '14 at 03:55
  • Okay give me a minute – klcjr89 Jan 23 '14 at 03:56
  • Works a treat I believe thank you so much! Here's what I did: - (void)findMisbehavingScrollViewsIn:(UIView *)view { if ([view isKindOfClass:[UICollectionView class]]) { NSLog(@"Found UIScrollView: %@", view); if ([(UIScrollView *)view scrollsToTop]) { UIScrollView *theView = (UIScrollView*)view; theView.scrollsToTop = NO; } } for (UIView *subview in [view subviews]) { [self findMisbehavingScrollViewsIn:subview]; } } – klcjr89 Jan 23 '14 at 04:00
  • You're welcome! I'm glad I could help. I've encountered this kind of issue once too, and I know how annoying can it be to fix it :) – arturgrigor Jan 23 '14 at 04:05
  • What's even greater is that my detail webView controller within my Settings table view controller (pushed on the stack) behaves properly too, woot! – klcjr89 Jan 23 '14 at 04:09
  • Looks like im still having a slight issue with the webview interfering with another scroll view – klcjr89 Jan 23 '14 at 04:27
  • Nevermind, solved that as well with some NSNotifications – klcjr89 Jan 23 '14 at 04:45