scrollsToTop not working with UIViewController con

2019-04-22 02:21发布

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?

5条回答
我想做一个坏孩纸
2楼-- · 2019-04-22 02:28

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;
}
查看更多
Viruses.
3楼-- · 2019-04-22 02:35

I have used this and now it works fine.

- (void)viewDidLoad
{
    [super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.

    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];
    lTableView1.tag=1;

    UIViewController *lViewController2 = [[UIViewController alloc] init];
    UITableView *lTableView2 = [[UITableView alloc] initWithFrame: self.view.frame];
    lTableView2.scrollsToTop = NO;
    [lViewController2.view addSubview: lTableView2];
    lTableView2.dataSource = self;
    [self.view addSubview: lViewController2.view];
    [self addChildViewController: lViewController2];
    lTableView2.tag=2;
    // now hide the view in view controller 2
    lViewController2.view.hidden = YES;

}

- (NSUInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSUInteger)section {
    return 50;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath      *)indexPath {
    static NSString * const kCellIdentifier = @"MyCell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kCellIdentifier];
    }
    cell.textLabel.text = [NSString stringWithFormat:@"hello %d %d",indexPath.row, tableView.tag];
    return cell;
}
查看更多
走好不送
4楼-- · 2019-04-22 02:42

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.

查看更多
相关推荐>>
5楼-- · 2019-04-22 02:49

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!

查看更多
在下西门庆
6楼-- · 2019-04-22 02:53

After testing several options and various hits and try I finally settled to one final solution, i.e. setBounds: of scrollView (that is tableView in your case) and it works good. You'll have to put extra effort for animation although.

    CGRect frame = scrollView.frame;
    frame.origin.x = 0;
    frame.origin.y = 0;
    [scrollView setBounds:frame];

By the way in your case, try returning YES to

- (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView;

Although if not defined, assumes YES.

查看更多
登录 后发表回答