14
votes

I'm trying to animate a tableview's offset down, then in the completion block would move it back up. But my code is not doing anything in the completion block:

-(void)viewDidAppear:(BOOL)animated {
    if (TRUE) {
         NSLog(@"animating table view");

        [UIView animateWithDuration:.25
                         animations:^{
                             self.tableView.contentOffset = CGPointMake(self.tableView.contentOffset.x, self.tableView.contentOffset.y - 60);
                         }
                         completion:^(BOOL finished){
                             NSLog(@"completion block");
                         }];
    }
}

"completion block" never gets outputted... any ideas?

EDIT:

Ok, so it has something to do with my UIREfreshControl:

- (void)viewDidLoad
{
    [super viewDidLoad];

    if (TRUE) {
        UIRefreshControl *refresh = [[UIRefreshControl alloc] init];
        refresh.attributedTitle = [[NSAttributedString alloc] initWithString:@"Pull to Refresh"];
        [refresh addTarget:self action:@selector(refreshTableView:) forControlEvents:UIControlEventValueChanged];

        [self setRefreshControl:refresh];
    }
}

When the refresh controll is added, it won't fire off the completion block. if i dont' add the control, it works as intended.

EDIT 2:

K, so if i scroll the table view, the completion block is then fired:

2013-02-15 13:37:06.266 [1922:14003] animating table view
2013-02-15 13:37:14.782 [1922:14003] completion block

the code as written should log "completion block" right after "animating table view", but it has a 8 second delay cause thats when i scrolled the table view myself.

how the "Pull to Refresh" looks like:

enter image description here

2
just tryed your code on test project, and 'completion block' is ouputed to console. You tryed this on simulator or on device. Which iOS version you used, XCode version?jamapag
Simulator, iOS 6.1, xcode 4.6. You did this in the viewDidAppear: method?Padin215
Hmm, I have same setup. Is viewDidAppear get called?jamapag
Works for me. Xcode 4.6. I tested in the 5.0 simulator and the 6.1 simulator and both worked correctly.rob mayoff
Ok, updated my questionPadin215

2 Answers

8
votes

I was able to reproduce this issue and found a workaround.

When using a UIScrollView, which UITableView inherits from, you can't change its contentOffset is not an animatable property. Instead, you need to use the method setContentOffset:animated:.

So, what you need to do is as follows:

  1. Set your view controller as the UITableView delegate. I did in on viewDidAppear.
  2. Set a flag, so you know in the delegate that the scroll happened because you triggered.
  3. In the delegate method - (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView, bounce back the animation (you could here add a delay by using performSelector:afterDelay:.

Here's the code:

@interface MyViewController ()

@property (assign, nonatomic) BOOL shouldReturn;

@end

@implementation MyViewController

-(void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    if (TRUE) {
        NSLog(@"animating table view");
        self.shouldReturn = YES;
        self.tableView.delegate = self;
        [self.tableView setContentOffset:
                     CGPointMake(self.tableView.contentOffset.x,
                                 self.tableView.contentOffset.y - 60)
                                animated:YES];
    }
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    if (TRUE) {
        UIRefreshControl *refresh = [[UIRefreshControl alloc] init];
        refresh.attributedTitle = [[NSAttributedString alloc] initWithString:@"Pull to Refresh"];
        [refresh addTarget:self action:@selector(refreshTableView:) forControlEvents:UIControlEventValueChanged];

        [self setRefreshControl:refresh];
    }
}

- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView {
    if (self.shouldReturn) {
        self.shouldReturn = NO;
        [self.tableView setContentOffset:CGPointZero animated:YES];
    }
}

@end
14
votes

I used this and working fine. Its alternative solution.

[UIView animateWithDuration:0.5
                              delay:0.1
                            options: UIViewAnimationOptionCurveEaseOut
                         animations:^
         {
             CGRect frame = self.adBannerView.frame;

             self.adBannerView.frame = frame;
         }
                         completion:^(BOOL finished)
         {
         }];

try adding delay and options.