Я столкнулся с такой же проблемой в последнее время, и потребовалось некоторое время, чтобы ее исправить. Проблема заключается в том, что когда текстовое поле вложено в ReusableCollectionView, следующее не работает.
[self.collectionView reloadData];
[self.textField becomeFirstResponder];
Кроме того, для меня он отлично работал на симуляторе, но не работал на устройстве.
Настройка контроллера представления как текстовое поле делегат и реализации
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField {
return NO;
}
не работает, потому что, как вид коллекции результата не обновить. Моя догадка заключается в том, что до перезагрузки коллекции его взглядов пытается удалить фокус из всех вложенных элементов управления, но это невозможно - мы возвращаем NO из метода делегата текстового поля.
Итак, решение для меня состояло в том, чтобы позволить системе удалить фокус из текстового поля, а затем вернуть его после перезагрузки. Вопрос в том, когда на самом деле это делать.
Во-первых, я пытался сделать это в
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
но когда не было никаких элементов в коллекции (что обычно и бывает во время фильтрации) этот метод не дозвонились.
В конце концов я решил это следующим образом. Я создал подкласс UICollectionReusableView, реализующий два метода: -prepareForReuse и -drawRect :. Первый содержит вызов -setNeedsDesplay, который планирует drawRect вызывать следующий цикл рисования. Второй восстанавливает фокус, вызывая [self.textField статьFirstResponder], если для соответствующего флага установлено значение YES. Таким образом, идея заключалась в том, чтобы называть beFirstResponder «позже», но не слишком поздно, иначе происходит странное «прыжки» клавиатуры.
Мой заказ многоразовые вид коллекции выглядит следующим образом:
@interface MyCollectionReusableView : UICollectionReusableView
@property (nonatomic, assign) BOOL restoreFocus;
@property (nonatomic, strong) UITextField *textField;
@end
@implementation MyCollectionReusableView
@synthesize restoreFocus;
@synthesize textField;
- (void)setTextField:(UITextField *)value {
textField = value;
[self addSubview:textField];
}
- (void)drawRect:(CGRect)rect {
[super drawRect:rect];
if (self.restoreFocus) {
[self.textField becomeFirstResponder];
}
}
- (void)prepareForReuse {
[self setNeedsDisplay];
}
Тогда в моем View Controller:
- (void)viewDidLoad {
[super viewDidLoad];
[self.collectionView registerClass:[MyCollectionReusableView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:HeaderReuseIdentifier];
[self.textField addTarget:self action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
}
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath {
if (UICollectionElementKindSectionHeader == kind) {
MyCollectionReusableView *view = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:HeaderReuseIdentifier forIndexPath:indexPath];
//add textField to the reusable view
if (nil == view.textField) {
view.textField = self.textField;
}
//set restore focus flag to the reusable view
view.restoreFocus = self.restoreFocus;
self.restoreFocus = NO;
return view;
}
return nil;
}
- (void)textFieldDidChange:(UITextField *)textField {
self.restoreFocus = YES;
[self.collectionView reloadData];
}
Вероятно, не самое элегантное решение, но это работает. :)
Спасибо, что задали этот вопрос. – GeneCode