Я хочу сделать ряд вещей в ответ на конец некоторых анимаций UITableView. Например, я хочу, чтобы ячейка представления таблицы выделяла (через selectRowAtIndexPath) после прокрутки через scrollToRowAtIndexPath.
Как это можно сделать?
Я хочу сделать ряд вещей в ответ на конец некоторых анимаций UITableView. Например, я хочу, чтобы ячейка представления таблицы выделяла (через selectRowAtIndexPath) после прокрутки через scrollToRowAtIndexPath.
Как это можно сделать?
Основной шаблон:
[UIView animateWithDuration:0.2 animations:^{
//do some animations, call them with animated:NO
} completion:^(BOOL finished){
//Do something after animations finished
}];
Пример: прокрутите до строки 100. По завершении найдите ячейку в этой строке и сделайте представление содержимого ячейки с тегом = 1 первому ответу:
[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];
}];
Я понимаю это старое сообщение, но у меня была аналогичная проблема, и я создал решение, которое хорошо работало для меня. Я применил методы, используемые в NSCookBook для создания UIAlertViews с блоками. Причина, по которой я пошел на это, заключалась в том, что я хотел использовать встроенные анимации, а не UIView + animateWithDuration: animations: complete:. Существует большая разница между этими анимациями с изменением на 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");
}
];
Хорошо, если вы хотите выполнить действие после запуска 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