UIView Animate and completion block

ios, objective-c

Solution

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:

- Set your view controller as the `UITableView` delegate. I did in on `viewDidAppear`.

- Set a flag, so you know in the delegate that the scroll happened because you triggered.

- 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

Problem

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:

Original source