如何禁用TPKeyboardAvoidingTableView编辑TextField时的自动滚动
嘿,我看你遇上了个挺闹心的问题:用TPKeyboardAvoidingTableView的时候,编辑最后一个单元格里的TextField,表格居然自动滚到顶部,根本没法好好输入。结合你贴的代码,我给你整理了几个靠谱的解决思路:
1. 先把多余的beginUpdates删掉,直接更新Cell内容
你代码里调用了[self.tableHSEMonthlyReport beginUpdates],但你只是更新现有单元格的总计标签,又没增删移动行,这个调用反而会触发表格重新计算布局,很可能就是它搞乱了滚动位置。直接去掉它,再加上保存恢复滚动位置的逻辑就行:
dispatch_async(dispatch_get_main_queue(), ^(void){ // 先把当前的滚动位置存下来 CGPoint currentOffset = self.tableHSEMonthlyReport.contentOffset; NSIndexPath* indexPath = [NSIndexPath indexPathForRow:txtIndPath.row inSection:txtIndPath.section]; HSEMonthlyPerformanceTableViewCell *cell = [self.tableHSEMonthlyReport cellForRowAtIndexPath:indexPath]; if (cell) { // 这里换成你实际计算总分的逻辑哈 CGFloat score1 = [[((HSEMonthlyGeneralQuestion*)arrayGeneralQuestions[txtIndPath.row]).score1 floatValue]; CGFloat score3 = [[((HSEMonthlyGeneralQuestion*)arrayGeneralQuestions[txtIndPath.row]).score3 floatValue]; cell.lblTotal.text = [NSString stringWithFormat:@"%.2f", score1 + score3]; } // 强制把滚动位置拉回之前的地方,不让它乱跑 [self.tableHSEMonthlyReport setContentOffset:currentOffset animated:NO]; });
2. 实在不行,就临时管住TPKeyboardAvoiding的自动滚动
如果上面的方法还压不住,那可能是TPKeyboardAvoiding自带的键盘监听逻辑在捣乱。你可以在开始编辑的时候记好当前位置,等键盘弹出来的时候强行把表格拉回去:
首先在你的ViewController里加个变量存编辑时的滚动位置和当前编辑的TextField:
@property (nonatomic, assign) CGPoint editingContentOffset; @property (nonatomic, weak) UITextField *activeTextField;
然后在textFieldDidBeginEditing:里记录位置和当前TextField:
- (void)textFieldDidBeginEditing:(UITextField *)textField { self.editingContentOffset = self.tableHSEMonthlyReport.contentOffset; self.activeTextField = textField; }
接着监听键盘弹出事件,只在编辑最后一个Cell的时候强制恢复位置:
// 记得在viewDidLoad里加监听 - (void)viewDidLoad { [super viewDidLoad]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; } - (void)keyboardWillShow:(NSNotification *)notification { // 先找到当前编辑的Cell的位置 CGPoint textFieldPoint = [self.activeTextField convertPoint:CGPointZero toView:self.tableHSEMonthlyReport]; NSIndexPath *txtIndPath = [self.tableHSEMonthlyReport indexPathForRowAtPoint:textFieldPoint]; // 只有编辑最后一个Cell的时候才强制拉回位置 if (txtIndPath.row == arrayGeneralQuestions.count - 1) { [self.tableHSEMonthlyReport setContentOffset:self.editingContentOffset animated:NO]; } } // 别忘了在dealloc里移除监听,避免内存泄漏 - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; }
3. 顺便检查下数据源的线程安全
你在后台线程修改了arrayMonthlyGeneralQustion和arrayGeneralQuestions,虽然replaceObjectAtIndex:是原子操作,但如果其他地方也在访问这两个数组,可能会导致数据乱掉,间接让表格布局出问题。可以加个串行队列把数据源操作包起来,确保线程安全:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){ // 创建一个串行队列,所有数据源操作都走这个队列 static dispatch_queue_t dataQueue; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ dataQueue = dispatch_queue_create("com.yourApp.hseDataQueue", DISPATCH_QUEUE_SERIAL); }); dispatch_sync(dataQueue, ^{ [[HSEAppData appData].arrayMonthlyGeneralQustion replaceObjectAtIndex:txtIndPath.row withObject:dic]; [arrayGeneralQuestions replaceObjectAtIndex:txtIndPath.row withObject:question]; }); // 主线程更新UI的代码... });
小提醒
另外你可以检查下Cell的高度计算逻辑,确保它是固定的或者不会在编辑时突然变化,高度跳变也会导致表格滚动异常哦。
内容的提问来源于stack exchange,提问作者Manju Sreejith

