Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

scrollsToTop not working with UIViewController containment

Using SDK 6.1, Xcode 4.6.1, I make a new project Master-Detail iOS App, ARC, no storyboards.

Then in the DetailViewController, in the viewDidLoad I add two UITableViews contained in UIViewControllers and make sure the second one is hidden like this:

- (void)viewDidLoad
{
    [super viewDidLoad];

    UIViewController *lViewController1 = [[UIViewController alloc] init];
    UITableView *lTableView1 = [[UITableView alloc] initWithFrame: self.view.frame];
    lTableView1.scrollsToTop = YES;
    [lViewController1.view addSubview: lTableView1];
    lTableView1.dataSource = self;
    [self.view addSubview: lViewController1.view];
    [self addChildViewController: lViewController1];

    UIViewController *lViewController2 = [[UIViewController alloc] init];
    UITableView *lTableView2 = [[UITableView alloc] initWithFrame: self.view.frame];
    lTableView2.scrollsToTop = YES;
    [lViewController2.view addSubview: lTableView2];
    lTableView2.dataSource = self;
    [self.view addSubview: lViewController2.view];
    [self addChildViewController: lViewController2];

    // now hide the view in view controller 2
    lViewController2.view.hidden = YES;
}

(I make sure the DetailViewController is a datasource that returns 100 rows of UITableViewCells with the textLabel.text set to @"hello")

The presence of the second view controller makes that scrollsToTop (tapping on the status bar) does not work anymore. If I do not use UIViewController containment and just add two UITableViews and set the second one to be hidden, scrollsToTop does work.

What am I doing wrong?

like image 239
Kristof Van Landschoot Avatar asked Apr 12 '13 15:04

Kristof Van Landschoot


3 Answers

scrollsToTop only works on a single visible view. From the documentation:

This gesture works on a single visible scroll view; if there are multiple scroll views (for example, a date picker) with this property set, or if the delegate returns NO in scrollViewShouldScrollToTop:, UIScrollView ignores the request. After the scroll view scrolls to the top of the content view, it sends the delegate a scrollViewDidScrollToTop: message.

You could try calling [tableView setContentOffset:CGPointZero animated:YES] on each of your table (or scroll) views manually instead. To do this, implement the scrollViewShouldScrollToTop: method in the UIScrollViewDelegate protocol:

- (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView {
    [lTableView1 setContentOffset:CGPointZero animated:YES];
    [lTableView2 setContentOffset:CGPointZero animated:YES];
    return NO;
}
like image 119
Goblin Avatar answered Nov 07 '22 01:11

Goblin


You can only set 1 ScrollView per ViewController with property .scrollsToTop = YES. If you set 2 scrollview.scrollsTopTop = YES, it will simply stop functioning.

ie: your sample project (DetailViewController.m) update following lines,

line48:    lTableView1.scrollsToTop = YES; 
line56:    lTableView2.scrollsToTop = NO;

then, scrollsToTop works correctly. If there are more than 1 scrollview you wish to concurrently setScrollsToTop, keep digging around. good luck!

like image 35
dklt Avatar answered Nov 07 '22 02:11

dklt


I am currently experimenting with your project. When

lViewController2.view.hidden = YES;

is replaced with

lTableView2.hidden = YES;

then the scrolling works, even with controller containment.

I tried to insert a view between the controller's view and the table and then hide this view, but the table was not scrolling.

I tried to hide the controller by experimenting with shouldAutomaticallyForwardAppearanceMethods but the table was not scrolling.

Result: From my experiments, only one scroll view must be visible in the view hierarchy and the hidden property of the parent views is not checked out. hidden must be set to NO on all other scroll views, not their parent views.

like image 36
Sulthan Avatar answered Nov 07 '22 03:11

Sulthan