Denis Kutlubaev
Denis Kutlubaev

Reputation: 16114

scrollsToTop does not work

I am using PPRevealSideViewController. I have two ViewControllers in it. The middle one is a subclass of SideSwipeTableViewController and the left one is a subclass of UIViewController, that has a tableView inside it. Example apps for PPRevealSideViewController and SideSwipeTableViewController are both supporting scrollsToTop property for UITableView at least for the TableView that is in the mid of PPRevealSideViewController. But when I use both of these classes, scrollsToTop stops working.

I know this is similar question, but I have tried everything, I have read all posts, that google gives me about this problem, but still couldn't solve it. So I decided to ask it here, I don't have any ideas even what to do, to make scrollsToTop work.

self.window.rootViewController = self.revealSideViewController;

Where

- (PPRevealSideViewController *)revealSideViewController
{
    if (! _revealSideViewController) {
        _middleTableViewController = [MiddleTableViewController new];
        UINavigationController *middleNavController = [[UINavigationController alloc] initWithRootViewController:_middleTableViewController];
        _revealSideViewController = [[PPRevealSideViewController alloc] initWithRootViewController:middleNavController];
        _revealSideViewController.delegate = self;
    }

    return _revealSideViewController;
}

    - (void) preloadSidePanel
{
    AppDel.systemTableViewController = [SystemTableViewController new];
    AppDel.systemTableViewController.parent = self;
    [self.revealSideViewController preloadViewController:AppDel.systemTableViewController
                                                 forSide:isLeftHanded ? PPRevealSideDirectionLeft : PPRevealSideDirectionRight
                                              withOffset:_offset];
}

And I set in this systemTableViewController this:

_tableView = [[UITableView alloc] initWithFrame:frame style:UITableViewStylePlain];
[self.view addSubview:_tableView];
 _tableView.scrollsToTop = NO;

However, it doesn't help.

Upvotes: 4

Views: 4514

Answers (6)

DennyLou
DennyLou

Reputation: 313

I know this is quite an old one but hope this can help. Following the rule that scrollsToTop doesn't work if more than one UIScrollView, or its subclasses, has got it set to YES (default value), a sanity check is probably worth to check who's actually messing up with this behaviour. The simple method below loop over the subviews of your view and logs the scrollsToTop value of all the UIScrollView in your view. Preferably to be called in your viewDidAppear method.

- (void)checkForScrollViewInView:(UIView *)view {
    for (UIView *subview in [view subviews]) {
        if ([subview isKindOfClass:[UIScrollView class]]) {
            NSLog(@"scrollsToTop enabled: %i in scroll view %@", ((UIScrollView *)subview).scrollsToTop, subview);
        }
        if (subview.subviews.count > 0) {
            [self checkForScrollViewInView:subview];
        }
    }
}

This is just a debug code indeed. Once you find the scrollsToTop value for each one of the UIScrollView subclasses just make sure only one is set to YES.

Upvotes: 0

user
user

Reputation: 3456

I thought I was cursed by the ghost of Jobs because I tried every possible solution from all related questions here on StackOverflow, and I could not get my scrollviews to cooperate.

If none of the above answers work for you- make sure you don't have a UIScrollView or a subclass inside your tableview cells. Looping through your view's subviews and disabling scrollsToTop will do nothing if your tableView has not already loaded it's subviews.

The solution that worked for me was creating a public disableScrollsToTop method on my UITableViewCell subclass that sets the scrollsToTop property of its scrolling subview to NO.

The code I used (with names generalized):

MYViewController.m

- (void)viewDidLoad
{
    // ... your initialization code
    [self setupScrollViewScrolling];
}

- (void)setupScrollViewScrolling
{
    self.horizontalScrollView.scrollsToTop = NO;
    self.tableView.scrollsToTop = YES;
}

// Note that I am using Xibs here, and your implementation for storyboards/xibless will be slightly different. 
- (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:
    MyTableViewCell *cell;
    static NSString *identifier = @"IdentifierForCell";
    if (!(cell = [self.tableView dequeueReusableCellWithIdentifier:identifier])) 
    {
        [[NSBundle mainBundle] loadNibNamed:@"MYTableViewCell" owner:self options:nil];
        cell = self.tableViewCell;
        self.tableViewCell = nil;
        // ... cell initialization code
        [cell disableScrollsToTop];
    }

    return cell;
}

And of course, disableScrollsToTop is just

MYTableViewCell.m

- (void)disableScrollsToTop
{
    self.subviewThatScrolls.scrollsToTop = NO;
}

Another way (that is arguably more extensible) this could be done is wrapping UITableView's reloadData method, and after the reload calling a recursive scrollview-checking method like what @Dominic_Sander listed above, although I have not checked this solution since I am done messing with this problem.

Upvotes: 0

malex
malex

Reputation: 10096

If you have tried all the solutions mentioned in similar threads here and have not succeeded in "scrollsToTop repair" you only need to subclass main UIWindow of your App.

@interface CustomWindow : UIWindow
@end

@implementation CustomWindow

-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
    if (point.y <= 20) {
        //do something to scroll appropriate UIScrollView to top
    }
    return YES;
}

Use this in AppDelegate:

#import "CustomWindow.h"

@interface AppDelegate : UIResponder

@property (nonatomic,strong) CustomWindow *window;

@end

This solution allows one to set any UIScrollView of your App to be scrolled to top ignoring general scrollsToTop mechanism.

All you need is to have a global link pointing to "active" UIScrollView at the moment.

Upvotes: 1

hfossli
hfossli

Reputation: 22962

I hope this class can be to help. In my app we're having multiple webviews and scrollviews. This makes it all much easier. :)

https://gist.github.com/hfossli/6776203

Good luck!

Upvotes: 1

Dominic Sander
Dominic Sander

Reputation: 2704

With the following little Extension of UIView I solved the same issue. Because these property doesn' ´t only exist on UITableView, but also on UIScrollView and ancestors (e.g. UICollectionView).

@implementation UIView (UIViewPimp)

- (void) disableScrollsToTopPropertyOnMeAndAllSubviews {
    if ([self isKindOfClass:[UIScrollView class]]) {
        ((UIScrollView *)self).scrollsToTop = NO;
    }
    for (UIView *subview in self.subviews) {
        [subview disableScrollsToTopPropertyOnMeAndAllSubviews];
    }
}
@end

I call these new method in the viewDidLoad-Method and then I set the property of the desired UITableViewexplicit.

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self.view  disableScrollsToTopPropertyOnMeAndAllSubviews];
    self.myTableView.scrollsToTop = YES;
}

Upvotes: 5

Rahul Wakade
Rahul Wakade

Reputation: 4805

Scroll to top works only if there is only one scroll view(or any subclass of scroll view. In your case it is table view) is visible.

Even if there are multiple scroll views visible, only one should have this property set then only it will work.

Also if the delegate returns NO in scrollViewShouldScrollToTop, it will not work.

Upvotes: 8

Related Questions