UITableView reloadData automatically calls resignF

2019-01-11 00:42发布

I have this UITableView with custom cells that can get only predefined values, therefore I use a UIPickerView as their inputView. All is jolly good until I edit a field and need to show its updated value.

In order to make things clearer and easier to maintain, I made delegates and data sources as separate classes, and use notifications to make them interact with the tableView. So, after a value has been chosen from the UIPickerView, the tableView's data source gets notified, and in turn notifies the main ViewController that holds a reference to the tableView. From there I call

[_tableView reloadData];

and everything seems to work, except that the UIPickerView disappears, I think because the cells are regenerated and somewhere some resignFirstResponder is called, or something like that. Is there any other way to make the tableView updating its values without having to implement a custom method somewhere that does it, which would be quite ugly?

13条回答
啃猪蹄的小仙女
2楼-- · 2019-01-11 00:50

I met the same problem, none of the answers above worked perfectly (I see the keyboard bouncing up and down, etc.).
Following this SO post I fixed the issue by calling

[tableView beginUpdates];
[tableView endUpdates]; 

this worked for me, table rows get updates and even expand/shrink (if you are changing rows height dynamically) with a nice animation, all without resigning first responder or even starting keyboard dismiss.
This will not scroll your table view to fit any expanded row, so I put the snippet above in dedicated method, f.e.:

- (void)tableView:(UITableView *)tableView reloadRowWhileShowingKeyboard:(NSIndexPath *)indexPath 
{  
    [tableView beginUpdates];
    [tableView endUpdates]; 

    [tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
查看更多
仙女界的扛把子
3楼-- · 2019-01-11 00:51

adding:

[yourSearchBar becomeFirstResponder];

after your:

[_tableView reloadData];

did the trick

查看更多
可以哭但决不认输i
4楼-- · 2019-01-11 00:51

I solved this by subclassing UITextView, overriding -(BOOL)resignFirstResponder and by adding a BOOL canResign. this variable is set before reloading the data and unset a short time after.

查看更多
神经病院院长
5楼-- · 2019-01-11 00:51

As mentioned by @Eiko, this works for me!

Update the cell in UIPickerViewDelegate's pickerView:didSelectRow:inComponent: method:

- (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];
}
查看更多
闹够了就滚
6楼-- · 2019-01-11 00:53

Track which cell's keyboard is active and then get that particular cell by cellForRowAtIndexPath and make textView firstResponder

self.tableView.reloadData()
if let indexPath = self.activeIndexPath{
   if let cell = createFormTableView.cellForRow(at: indexPath) as? TextViewTableViewCell {
        cell.txtViewInput.becomeFirstResponder()
   }
}
查看更多
祖国的老花朵
7楼-- · 2019-01-11 00:55

Swift solution:

we can override default canResignFirstResponder by subclassing UITextfiled

class CustomField: UITextField{
    var canResign:Bool = false
    override var canResignFirstResponder: Bool{
        return canResign
    }  
}

all you need to set canResign variable before and after reload statement.

cell.offerInputTextField.canResign = false
tableView.reloadData()
cell.offerInputTextField.canResign = true

don't forget to assign the custom class text field as CustomField.

查看更多
登录 后发表回答