[ACCEPTED]-UITableView reloadData automatically calls resignFirstResponder-resignfirstresponder
This reads like expected behavior - the 8 picker belongs to a particular cell, that 7 cell gets reloaded and is not the first 6 responder any more. I guess one had to select 5 a specific element anyway for the picker 4 to appear, i.e. to make it first responder.
So 3 you either need to make it become first 2 responder again after reloading, or update 1 the specific cell directly.
adding:
[yourSearchBar becomeFirstResponder];
after your:
[_tableView reloadData];
did the trick
0
I met the same problem, none of the answers 10 above worked perfectly (I see the keyboard 9 bouncing up and down, etc.).
Following this SO post I 8 fixed the issue by calling
[tableView beginUpdates];
[tableView endUpdates];
this worked for 7 me, table rows get updates and even expand/shrink 6 (if you are changing rows height dynamically) with 5 a nice animation, all without resigning 4 first responder or even starting keyboard 3 dismiss.
This will not scroll your table 2 view to fit any expanded row, so I put the 1 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];
}
You can follow this approach, not the best, but 1 it works:
// 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];
});
I solved this by subclassing UITextView, overriding 4 -(BOOL)resignFirstResponder and by adding 3 a BOOL canResign. this variable is set before 2 reloading the data and unset a short time 1 after.
customTextField.canResign = NO;
[self.tableView reloadData];
customTextField.canResign = YES;
Custom text field is derived from UITextField.
.h
@interface CustomTextField : UITextField
@property (nonatomic,assign) BOOL canResign;
@end
.m
- (BOOL)canResignFirstResponder
{
return self.canResign;
}
Make 2 sure that your custom text field is not recreated on 1 table view reloading.
I put my UISearchBar in its own section 3 in a UITableView. When firing off the search, I 2 made sure to only refresh the sections which 1 do not contain the search bar.
- (void)reloadSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation
Swift solution:
we can override default canResignFirstResponder 4 by subclassing UITextfiled
class CustomField: UITextField{
var canResign:Bool = false
override var canResignFirstResponder: Bool{
return canResign
}
}
all you need to 3 set canResign variable before and after 2 reload statement.
cell.offerInputTextField.canResign = false
tableView.reloadData()
cell.offerInputTextField.canResign = true
don't forget to assign 1 the custom class text field as CustomField.
Here my solution. Think that search textfield 2 is in index 0.. You need to update or add 1 or remove next rows..
let beforeCount = self.filteredItems.count
self.filteredItem = ... next filtered items
var removalIndexPaths = [IndexPath]()
var appendalIndexPaths = [IndexPath](
var modifyIndexPaths = [IndexPath]()
self.tableView.beginUpdates()
let deleteAvailable = beforeCount != 0
if deleteAvailable {
for i in stride(from: beforeCount - 1, to: 0, by: -1) {
removalIndexPaths.append(IndexPath(row: i, section: 0))
}
}
let appendAvailable = self.filteredShots.count != 0
if appendAvailable {
for i in stride(from: 1, to: self.filteredShots.count, by: 1) {
appendalIndexPaths.append(IndexPath(row: i, section: 0))
}
}
modifyIndexPaths = appendalIndexPaths.filter { appendPath in
if appendPath == removalIndexPaths.filter({ $0 == appendPath }).first {
return true
} else {
return false
}
}
for item in modifyIndexPaths {
if let rai = appendalIndexPaths.firstIndex(where: { $0 == item}) {
appendalIndexPaths.remove(at: rai)
}
if let rri = removalIndexPaths.firstIndex(where: { $0 == item}) {
removalIndexPaths.remove(at: rri)
}
}
if modifyIndexPaths.count > 0 {
self.tableView.reloadRows(at: modifyIndexPaths, with: .none)
}
if removalIndexPaths.count > 0 {
self.tableView.deleteRows(at: removalIndexPaths, with: .none)
}
if appendalIndexPaths.count > 0 {
self.tableView.insertRows(at: appendalIndexPaths, with: .none)
}
self.tableView.endUpdates()
If you are facing this issue with a search 2 bar, the following did it for me in iOS 1 6:
- Instantiate a UISearchBar and add it as a subview to your UITableView at the top.
- Create a dummy first cell in your UITableView so that the search bar only blocks this dummy cell and not your actual cell with data.
As mentioned by @Eiko, this works for me!
Update 1 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];
}
Track which cell's keyboard is active and 2 then get that particular cell by cellForRowAtIndexPath
and make 1 textView firstResponder
self.tableView.reloadData()
if let indexPath = self.activeIndexPath{
if let cell = createFormTableView.cellForRow(at: indexPath) as? TextViewTableViewCell {
cell.txtViewInput.becomeFirstResponder()
}
}
I use beginUpdate and endUpdate After end update, get the cell 2 contains the textfield already has focus 1 then make it first responder
self.tableView.beginUpdates()
self.tableView.reloadRows(at: [indexPath], with: .automatic)
self.tableView.endUpdates()
let newCell = self.tableView.cellForRow(at: indexPath)
newCell.textField.becomeFirstResponder()
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.