如何知道UITableView动画何时完成?

时间:2009-08-27 07:56:39

标签: iphone uikit

我想对某些UITableView动画的结尾做一系列的反应。例如,我希望表视图单元格在通过scrollToRowAtIndexPath滚动到之后突出显示(通过selectRowAtIndexPath)。

如何做到这一点?

3 个答案:

答案 0 :(得分:29)

基本模板:

[UIView animateWithDuration:0.2 animations:^{
    //do some animations, call them with animated:NO
} completion:^(BOOL finished){
    //Do something after animations finished     
}];   

示例:滚动到第100行。完成后,获取此行的单元格,并将带有tag = 1的单元格内容视图发送到firstResponder:

[UIView animateWithDuration:0.2 animations:^{
        [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:100 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO];
    } completion:^(BOOL finished){
        //Do something after scrollToRowAtIndexPath finished, e.g.:
        UITableViewCell *nextCell = [self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:100 inSection:0]];
        [[nextCell.contentView viewWithTag:1] becomeFirstResponder];        
    }];   

答案 1 :(得分:2)

我意识到这是一个老帖子,但我遇到了类似的问题并创建了一个适合我的解决方案。我应用了NSCookBook上使用的技术来创建带有块的UIAlertViews。我之所以这样做是因为我想使用内置动画而不是UIView的+ animateWithDuration:动画:完成:这些动画与iOS 7的更改之间存在较大差异。

您可以为UITableView创建一个类别,并在实现文件中创建一个内部私有类,它将通过将其指定为tableview的委托来回调该块。问题是,在调用块之前,原始委托将“丢失”,因为新委托是将调用块的对象。这就是为什么我在调用块来重新分配原始UITableViewDelegate时发出通知来发送消息。此代码已经过测试,正在我的工作中。

// Header file
@interface UITableView (ScrollDelegateBlock)

-(void)scrollToRowAtIndexPath:(NSIndexPath *)indexPath
             atScrollPosition:(UITableViewScrollPosition)scrollPosition
                     animated:(BOOL)animated
               scrollFinished:(void (^)())scrollFinished;

@end


// Implementation file
#import "UITableView+ScrollDelegateBlock.h"
#import <objc/runtime.h>

NSString *const BLOCK_CALLED_NOTIFICATION = @"BlockCalled";

@interface ScrollDelegateWrapper : NSObject <UITableViewDelegate>

@property (copy) void(^scrollFinishedBlock)();

@end

@implementation ScrollDelegateWrapper

-(void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView {
    if (self.scrollFinishedBlock) {
        [[NSNotificationCenter defaultCenter] postNotificationName:BLOCK_CALLED_NOTIFICATION object:nil];
        self.scrollFinishedBlock();
    }
}

@end

static const char kScrollDelegateWrapper;

static id<UITableViewDelegate>previousDelegate;

@implementation UITableView (ScrollDelegateBlock)

-(void)scrollToRowAtIndexPath:(NSIndexPath *)indexPath
             atScrollPosition:(UITableViewScrollPosition)scrollPosition
                     animated:(BOOL)animated
               scrollFinished:(void (^)())scrollFinished {
    previousDelegate = self.delegate;
    ScrollDelegateWrapper *scrollDelegateWrapper = [[ScrollDelegateWrapper alloc] init];
    scrollDelegateWrapper.scrollFinishedBlock = scrollFinished;
    self.delegate = scrollDelegateWrapper;

    objc_setAssociatedObject(self, &kScrollDelegateWrapper, scrollDelegateWrapper, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

    [self scrollToRowAtIndexPath:indexPath atScrollPosition:scrollPosition animated:animated];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(blockCalled:)
                                                 name:BLOCK_CALLED_NOTIFICATION
                                               object:nil];
}

/*
 * Assigns delegate back to the original delegate
 */
-(void) blockCalled:(NSNotification *)notification {
    self.delegate = previousDelegate;
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:BLOCK_CALLED_NOTIFICATION
                                                  object:nil];
}

@end

然后您可以像使用块一样调用该方法:

[self.tableView scrollToRowAtIndexPath:self.currentPath
                          atScrollPosition:UITableViewScrollPositionMiddle
                                  animated:YES
                            scrollFinished:^{
                                NSLog(@"scrollFinished");
                            }
];

答案 2 :(得分:-3)

好吧,如果你想在触发scrollToRowAtIndexPath后执行一个动作。

- (void)scrollToRowAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated

您需要创建一个类似

的CAAnimation指针
CAAnimation *myAnimation;

然后将delgate设置为self

myAnimation.delegate = self;

执行此操作后,以下代理方法应在您可以放置​​代码的地方激活:

- (void)animationDidStart:(CAAnimation *)theAnimation

- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag