I have a UICollectionView with a header, some cells and a footer supplementary views. The header contains a UISearchBar. If I type something into the search field, the keyboard automatically dismisses after the first letter. I think it is caused by my -searchBar:textDidChange:, which contains code for refreshing the collection view (via -reloadData, because this is the only method I know which works).
My theory is, that reloading the UICollectionView causes it to become first responder, but that somehow does not work.
I have this line in my output every time the keyboard dismisses:
setting the first responder view of the collection view but we don't know its type (cell/header/footer)
I attempted to overwrite UICollectionView's -canBecomefirstResponder, but unfortunately that didn't work.
Any ideas how can I prevent UICollectionView to become the first responder after the reload?
I've had luck restoring the search bar as the first responder after updating the table view:
collectionView.reloadData()
searchBar.becomeFirstResponder()
Related
I am able to detect when a cell is removed from the UITableView by writing a handler for the method tableView:didEndDisplayingCell:forRowAtIndexPath:. This method is called whenever a cell is removed from the display. However, there is one exception.
When the cell has a UITextField and the field is the first responder, this method is never called even when it's scrolled off the display and the cells immediately before it and after it are.
The cell is also confirmed to be removed from the UITableView with a test while the cell is scrolled off the screen. The call to cellForRowAtIndexPath: returns nil under this condition.
I also subclassed the UITableViewCell and wrote a handler for removeFromSuperView. Again this method is called for all the cells when the are scrolled off the screen except when the cell has a UITextField and it is the first responder.
Another thing to note is that the UITextField in the cell accepts key input while it is scrolled off the screen and the call to cellForRowAtIndexPath: returns nil. I can see this when the cell is scrolled back into view.
Does anyone have any solutions for detecting when the cell is scrolled out of view, so that the controller can get access to the UITextField?
You could try to resign your first responder manually before the cell disappears. Depending on your requirements, this could be done in multiple ways, usually when the user starts scrolling. You could restore the first responder after he finishes scrolling, if the cell is still visible. Probably better from the graphical design point of view as well.
Alternatively, you could try to implement delegate's tableView:willDisplayCell:forRowAtIndexPath: and make a previous visible cells set, which you'd intersect with tableview's visibleCells array. The elements that are not in the current visibleCells but are in the previous were removed. Then assign a copy of visibleCells to previousVisibleCells.
This is probably a bug in Apple's code, you could file a radar for it.
I would like to know if there is a way to keep UIKeyboard up while reloading section in UITableView? I have UITextField inside a header view of UITableView's section. Typing into this UITextField fires action that requires a section to be updated (reloaded).
As a result of calling [tableView reloadSections:...] the keyboard hides itself, because UITextField loses it's firstResponder status.
I would like to achieve similar effect like when using UISearchBar component in UITableView.
Thanks!
If you reload, everything will get refreshed. When that happens, the current first responder is resigned and the keyboard is animated out. To avoid that you need to no reload...
You would need to update the visible cells directly and use insertRowsAtIndexPaths:withRowAnimation: and deleteRowsAtIndexPaths:withRowAnimation: to make changes to the number of rows the table is managing. In this way the section won't be reloaded and you will avoid any cell animations / refreshing of views.
The layout for one of my View Controllers is such: I have a scroll view embedded inside my VC. Inside my scroll view, I have a table view that consists of 5 cell. The first 3 cells consist of a textfield thats pulls its text from a dictionary and this changes depending on certain situations. These textfields are editable and so tapping on them brings up the keyboard, the issue however is that I would like my view to scroll when I tap on the text field because right now they keyboard hides the the third editable text field. Another issue is that at the moment, clicking outside teh table view doesnt cause the keyboard to be dismissed and so the only way of dismissing the keyboard is tapping on the return key. What I would like to happen is that when I tap on either one of the 3 editable fields, the scroll view ought to scroll up a certain number that I define (this is so that I can define how much to scroll depending on which row is currently selected). One of the issues I'm facing is that I can't directly reference these textfields in my VC since they're all created through one prototype cell. My thinking was that I could create a dictionary with the 3 textfields as keys and then the scrollview y coordinates as values and then use that. However , I wasn't sure how to do this in my situation (with the prototype cells). Would really appreciate if someone could show me some sample code on how to do this.
You can reference your text fields by calling cellForRowAtIndexPath: to get the UITableViewCell, then calling viewWithTag: to get your UITextField. Just assign the text fields a tag number. Also, set the text field's delegate to be your view controller so that you can respond to a user tapping to edit text.
In a UITableView where the cells contain UITextField objects, does having one of those UITextField objects be the first responder prevent its cell from being re-used?
For example, with a UITableView that has more rows than will fit on the screen, one can tap on a UITextField to bring up the keyboard for the field in that cell. Then scroll the table view to make that cell go off screen. When scrolling back to the cell, I can see calls to -tableView:cellForRowAtIndexPath: for all the cells, except the one that contains the UITextField that currently has first responder status.
This behavior leads me to believe that iOS is aware that my cell contains the first responder and thus chooses not to discard the cell, thus not needing to call the data source to get the cell when it scrolls back into view.
This behavior is desirable, but I am concerned because I have not seen any documentation that indicates that this behavior is guaranteed, and I would hate to rely on it if there are conditions where it isn't true.
Can anyone point me at some documentation about table view cell re-use and first responders that covers this situation?
There is no such reference in the official iOS SDK documentation. You are correct to be concerned that this behavior you are observing is not guaranteed and should not be relied upon.
I have a UITableViewController, a bunch of sections and rows, and for each row I added a UITextField as a subview, right aligned in the row itself.
If the users taps on the row, I locally save the indexPath, make the corresponding text field become the first responder and finally, when the keyboard appears, I make the table view scroll so that the row remains visible.
I am facing the problem to obtain the same behaviour when the user taps the text field instead. In this case the didSelectRowAtIndexPath: method isn't called, so I do not know how to tell the table view to scroll to make sure that the "selected" row is still visible.
Probably the whole process is not correct. Do you know a way to solve it?
Thanks a lot!
I'm not absolutely sure about this, but...
Set the userInteractionEnabled property of the UITextField to NO. This way, the touch goes "through" the control, tapping the UITableViewCell. When didSelectRowAtIndexPath: is called, set the userInteractionEnabled property of the UITextField to YES. When the editing is complete, change it back to NO.