UITextfield inside UITableViewCells - dismiss keyboard - ios

I have a couple of UITextfields in each table cell. By hitting the "Done" button or touching outside the keyboard, the keyboard should be dismissed.
My problem: the textFieldShouldEndEditing method is only called when I tap another textfield and the keyboard won't be dismissed.
I think i've implemented the necessary parts (Delegate and protocol methods).
Does anyone know what I'm missing here....?
Here is the code (the relevant part):
class myVC: UIViewController, UITableViewDataSource, UITableViewDelegate, UITextFieldDelegate {...
This is the cell setup...
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let tcell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "tbCell")
let textfield: UITextField = UITextField(frame:...
switch (indexPath.section) {
case 0: ...
case 1:
textfield.text = section2[indexPath.row]
tcell.addSubview(textfield)
textfield.delegate = self
return tcell
and this the protocol method:
func textFieldShouldEndEditing(textField: UITextField) -> Bool {
textField.resignFirstResponder()
print("method is called")
return true
}
Thank you!

I am giving this answer in Objective-C because I don't use Swift
tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag;
when you will scroll your tableview, and:
tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;
when you will touch outside textfield.

Swift 4.0
tableView.keyboardDismissMode = .onDrag
or
tableView.keyboardDismissMode = .interactive

why dont you try textFieldShouldReturn delegate of UITextfield.
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
[textField resignFirstResponder];
return NO;}

Related

How do I gain access to a custom UITableViewCell from textFieldDidEndEditing?

I have a custom UITableViewCell where I've added a UITextField, I'd like to perform some validation on the textfield and set a hasError property on the cell to maybe add a error label to the cell and change the textfield back color.
I'm not using a storyboard and creating my custom cell / UITableViewCell programatically.
I'm using textFieldDidEndEditing in my UIViewController to detect text changes and have no access to the cell, to set my hasError property.
I guess I could loop around the views / textfields by a tag to field the textfield then gain it's parent.
Or maybe I should implement my own version of textFieldDidEndEditing which then fires another event which has the cell and the textfield as parameters.
But I'm not sure if that's the best approach or how to fire an event.
You can use Protocol. https://developer.apple.com/library/archive/documentation/General/Conceptual/DevPedia-CocoaCore/Protocol.html
A simple example:
cellForRow
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = ....
cell.delegate = self
return cell
}
Your UITableViewCell subclass:
class Cell: UITableViewCell, UITextFieldDelegate {
// MARK: - Properties
weak var delegate: CellDelegate?
....
// MARK: - Functions
func textFieldDidEndEditing(_ textField: UITextField) {
self.delegate?.cell(self, textFieldDidEndDiting: textField)
}
}
Your Protocol
protocol CellDelegate: class {
func cell(_ cell: Cell, textFieldDidEndDiting textField: UITextField)
}
Then finally, conform your controller to that protocol like so:
class ViewController: UIViewController, CellDelegate {
func cell(_ cell: Cell, textFieldDidEndDiting textField: UITextField) {
}
}

Using a Subclass With Textfield Delegates

I have a subclass, CustomCell, which inherits from my parent class, CreateEvent. The subclass describes different cells for the table view cell, which is on the CreateEvent View controller. In one specific cell, I have a textfield but I am having trouble getting the value from that textfield when a user enters into the textfield. I am also having trouble dismissing the keyboard with outside touches and pressing the return key, but I am primarily focused on getting the text from the textfield. I am familiar with doing these functionalities on a normal swift file but because this is a subclass, I'm not sure what to do. What I've tried is to use:
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
entranceFeeTextField.resignFirstResponder()
return true
}
.. but this does not do the trick.
you need to give UiTextfeld delegate in UITableview Delegate method and your CustomCell looks like
class CustomCell: UITableViewCell {
#IBOutlet var textField: UIImageView!
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
and one more thing to implement UITextfield protocol in you view controller.and your controller looks like
class CreateEvent: UIViewController,UITableViewDataSource,UITableViewDelegate,UITextFieldDelegate {
//MARK: - Content TableView Methods
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("CustomCell", forIndexPath: indexPath) as! CustomCell
cell.textField.delegate = self // like delegate
return cell
}
//MARK: - UITextField Methods
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
}
i hope this will help

UITextView inside a UITableViewCell, how to resign textview's firstResponder when tableView scrolls?

I created a custom UITableViewCell, and a UITextView was put inside this prototype cell. When I click on this textView, keyboard can bounce automatically. However, if I want to hide the keyboard, I will have to click Return key. It isn't quite convenient.
Here's the question.
How can I resign the textView's firstResponder for hiding the keyboard when I scroll the tableview.
cellForRowAtIndex method is below.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = UITableViewCell()
if(indexPath.section == 0){
cell = self.tableView.dequeueReusableCellWithIdentifier("InputCell")!
let textView = cell.viewWithTag(102) as! UITextView
textView.editable = true
textView.keyboardType = UIKeyboardType.Default
textView.delegate = self
textView.targetForAction(#selector(FeedBackViewController.getTextViewInsideCell(_:)), withSender: textView)
}
if(indexPath.section == 1){
cell = self.tableView.dequeueReusableCellWithIdentifier("ConfirmButtonCell")!
let label = cell.textLabel
label?.text = "send"
label?.textAlignment = NSTextAlignment.Center
label?.textColor = UIColor.redColor()
}
return cell
}
Here are some methods I have implemented.
func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool{
if(text == "\n"){
textView.resignFirstResponder()
return false
}
return true
}
And I have no idea how to implement this method.
func scrollViewWillBeginDragging(scrollView: UIScrollView) {
}
You can try implement this on viewDidLoad, it will auto dismiss keyboard when tableview start dragging:
tableView.keyboardDismissMode = .Interactive or .OnDrag
UITableView inherited from UIScrollView that conforms to UIScrollViewDelegateProtocol. Try to override scrollViewDidScroll function from it and resign first responder from textview.
Be sure to assign tableView's delegate to your view controller, and then add the following code
func scrollViewDidScroll(scrollView: UIScrollView) {
yourTextView.resignFirstResponder()
}
As per docs scrollViewDidScroll
Tells the delegate when the user scrolls the content view within the receiver.
Update
Another approach to resign first responder is to set endEditing to true for your view:
Causes the view (or one of its embedded text fields) to resign the first responder status.
func scrollViewDidScroll(scrollView: UIScrollView) {
self.view.endEditing(true)
}
it is quite easy You can do same with storyboard too
open storyboard
select tableview or collection view
and select on Drag

Dissmissing Keyboard without Calling didSelectRowAtIndexPath

I have a ViewController which has textSearchTableView: UITableView and searchBar: UISearchBar
I added UITapGestureRecognizer to dissmis the keyboard
override func viewDidLoad() {
// ...
self.tap = UITapGestureRecognizer(target: self, action: "DissmissKeyboard")
self.tap.delegate = self
self.view.addGestureRecognizer(self.tap)
// ...
}
func DissmissKeyboard()
{
view.endEditing(true)
}
I have added this function to prevent breaking (didSelectRowAtIndexPath) function after selecting the cell
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
if touch.view.isDescendantOfView(self.textSearchTableView) {
return false
}
return true
}
But the problem is: when the keyboard is enabled and i want to dissmiss it,
if i click on the textSearchTableView, (didSelectRowAtIndexPath) will run
How can i dissmiss the keyboard if i click on the tableView without calling (didSelectRowAtIndexPath) ? and I don't want to break this function as well
I hope that I describe the problem well
Thanks a lot
Re-write your didSelectRowAtIndexPath like this:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if (self.searchBar.isFirstResponder())
{
self.searchBar.resignFirstResponder()
}
else
{
//Do something here
}
}
Alternatively: We usually use this approach in tableviews.
self.tableView.keyboardDismissMode = .OnDrag
This will dismiss keyboard when a drag begins in the tableview.
How about you have your tableview's delegate return nil for
- (NSIndexPath *)tableView:(UITableView *)tableView
willSelectRowAtIndexPath:(NSIndexPath *)indexPath
As willSelectRowAtIndexPath is probably what you want but not what you asked for: dismissing the keyboard is done by sending the first responder resignFirstResponder, for sake of answering the actual question.

iOS: Selecting through UITextView on custom UITableViewCell

I have a custom UITableViewCell with an image and UITextView property. The textview spans to the edge of the cell. My problem is tapping the textview does not register in didSelectRowAtIndexPath.
How can I make it so that I can "click through" my textview?
For UITextView set textView.userInteractionEnabled = false and if you have UITextField, set textField.userInteractionEnabled = false.
If you want the textView or textField to be editable after the cell with it is tapped, do something like this:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
let cell = tableView.cellForRowAtIndexPath(indexPath)! as UITableViewCell
// find first textField inside this cell and select it
for case let textField as UITextField in cell.subviews {
textField.userInteractionEnabled = true
textField.becomeFirstResponder()
return
}
// find first textView inside this cell and select it
for case let textView as UITextView in cell.subviews {
textView.userInteractionEnabled = true
textView.becomeFirstResponder()
return
}
}
Then make sure to disable user interaction after you finish editing:
func textFieldDidEndEditing(textField: UITextField) {
textField.userInteractionEnabled = false
// rest of the function
}
func textViewDidEndEditing(textView: UITextView) {
textView.userInteractionEnabled = false
// rest of the function
}
Don't forget to set the UITextFieldDelegate and/or UITextViewDelegate
I hope this helped someone :)
If you don't need it to be editable, just set your text view's enabled property to NO.
You can assign a delegate to your UITextView, and in its textViewShouldBeginEditing: method, you can manually call the didSelectRowAtIndexPath method. If you can't easily get the indexPath of the row to select, you can use a subclass of UITextView that has an indexPath property, and in cellForRowAtIndexPath: method, when you create your UITextView, set the indexPath property.

Resources