UITableView reloadData自动调用resignFirstResponder
我有这个UITableView自定义单元格,只能获取预定义的值,因此我使用UIPickerView作为他们的inputView。 直到我编辑一个字段,并需要显示其更新的值,所有的都非常好。
为了使事情更清楚和容易维护,我将委托和数据源作为单独的类,并使用通知使它们与tableView交互。 所以,从UIPickerView中select一个值之后,tableView的数据源会得到通知,并通知主ViewController持有对tableView的引用。 从那里我打电话
[_tableView reloadData];
和一切似乎工作,除了UIPickerView消失,我想因为单元格重新生成,并在某个地方resignFirstResponder被称为,或类似的东西。 有没有其他的方式来使tableView更新它的值,而不必实现一个自定义方法的地方,这将是相当丑陋?
这看起来像预期的行为 – select器属于一个特定的单元格,该单元格重新加载,不再是第一响应者。 我想我们必须select一个特定的元素来让选取者出现,也就是使其成为第一响应者。
因此,您需要在重新加载后再次成为第一响应者,或者直接更新特定单元格。
添加:
[yourSearchBar becomeFirstResponder];
在你的:
[_tableView reloadData];
做的伎俩
我遇到了同样的问题,上面的答案都没有完美的工作(我看到键盘上下跳动等)。
继这个SO后,我通过调用来解决这个问题
[tableView beginUpdates]; [tableView endUpdates];
这工作对我来说,表行得到更新,甚至扩大/缩小(如果你dynamic改变行高度)一个很好的animation,所有没有辞职的第一响应者,甚至开始键盘开除。
这不会滚动你的表视图,以适应任何扩大的行,所以我把上面的代码片段专用的方法,fe:
- (void)tableView:(UITableView *)tableView reloadRowWhileShowingKeyboard:(NSIndexPath *)indexPath { [tableView beginUpdates]; [tableView endUpdates]; [tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES]; }
我通过inheritanceUITextView来解决这个问题,覆盖 – (BOOL)resignFirstResponder和BOOL canResign。 这个variables是在重新加载数据之前设置的,而在之后的一小段时间内是未设置的
你可以按照这个方法,而不是最好的,但它的工作原理:
// pass the responder to a temporary (hidden) textField [_tmpTextField becomeFirstResponder]; // reload data [_tableView reloadData]; // reloadData is definitely async... // so pass the responder back in a timed op double delayInSeconds = 0.1; dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)); dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ [_textField becomeFirstResponder]; });
我把我的UISearchBar在UITableView自己的部分。 当closuressearch时,我确保只刷新不包含search栏的部分。
- (void)reloadSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation
customTextField.canResign = NO; [self.tableView reloadData]; customTextField.canResign = YES;
自定义文本字段是从UITextField派生的。
。H
@interface CustomTextField : UITextField @property (nonatomic,assign) BOOL canResign; @end
.M
- (BOOL)canResignFirstResponder { return self.canResign; }
确保您的自定义文本字段不重新创build表视图重新加载。
如果您正在使用search栏面临这个问题,那么以下是iOS 6中为我所做的:
- 实例化一个UISearchBar并将其作为子视图添加到顶层的UITableView中。
- 在您的UITableView中创build一个虚拟的第一个单元格,以便search栏只能阻止这个虚拟单元格,而不是实际的数据单元格。
正如@Eiko所提到的,这对我有用!
更新UIPickerViewDelegate的pickerView:didSelectRow:inComponent:
方法中的单元格:
- (void) pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component { TableViewCell *cell = (TableViewCell *)[self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:pickerView.tag inSection:0]]; /* Update your cell here. */ // Reload TableViewCell will resign the PickerView, so we need to focus it back. [self.tableView reloadData]; NSIndexPath* indexPath = [self.tableView indexPathForCell:cell]; NSArray* indexArray = [NSArray arrayWithObjects:indexPath, nil]; [self.tableView reloadRowsAtIndexPaths:indexArray withRowAnimation:UITableViewRowAnimationNone]; [cell.textField becomeFirstResponder]; }
您可以通过暂时将第一个响应者状态转移到其他对象来解决此问题。 通常你把input视图的控制权交给你的ViewController。 由于你的UIViewController也是从UIResponderinheritance的,所以你可以这样做:
在didSelect {….
[yourViewController becomeFirstRespoder];
[_tableView reloadData];
[yourInputField becomeFirstResponder];
….}
因此,表格重新加载后,您可以将firstResponder状态转回到您的标签/字段。 默认情况下,canBecomeFirstResponder设置为NO。 所以你可能需要在你的ViewController中覆盖它。 此外,你可能需要使你的视图控制器的inputView和你的UIPicker一样,否则它可能会closures你的select器并显示一个键盘。