Dmitrii Molev
Dmitrii Molev

Reputation: 103

First tap to the second UITextfield located inside tableviewcell didn't start editing (display cursor). Only the second tap works. Why?

I have a tableviewcell and three textfields inside. I click the fist one (is called "target") and input some number. The keyboard is displayed which could be dismissed by tapping Done button on the keyboard itself (resignFirstResponder() is attached to Done button).

When I try to edit the second textfield (is called "actual") without keyboard dismissal the cursor doesn't appear on my first tap to the textfield which means editing didn't start (image 1 below). I need to tap this textfield for the second time for the cursor to appear (image 2 below).

How can I make the cursor appear by the first tap to the second editing textfield?

And I do not want to hide my keyboard (launch resignFirstResponder()) when a user decides to continue input let say 4-5 fields in a row. So editing in a textfield should end and start when a user taps another textfield. He edits whatever textfields he needs and then hits Done on the keyboard at the end.

(In fact the cursor in the second textfield appears by the first tap if a user tapped first textfield but inputted nothing)

My code:

I highlight / dishighlight the border of editing textfield:

func textFieldShouldBeginEditing(textField: UITextField) -> Bool // highlight textfield when editing
{
    textField.layer.borderWidth = 1
    textField.layer.cornerRadius = 2
    textField.layer.borderColor = UIColor.blueColor().CGColor
    return true
}



func textFieldShouldEndEditing(textField: UITextField) -> Bool  // hide  highlight textfield when editing
{

    textField.layer.borderWidth = 1
    textField.layer.borderColor = UIColor.clearColor().CGColor

    return true
}

I assign text before input to a variable which I check later to prevent data processing if a user didn’t change the text:

func textFieldDidBeginEditing(textField: UITextField) // remember number before user input to prevent actions when no input
{
    textInEditField = textField.text!
}

func textFieldDidEndEditing(textField: UITextField)
{
    if  textField.text == textInEditField // no actions if field is empty or text is not changed
    {  
        return
    }

  … inputed text processing
} 

What I tried:

  1. tourchesBegan. But I read that it is used for plain view and doesn’t work with scrollview which is my case with tableview

    override func touchesBegan(touches: Set<UITouch>, withEvent event:
    UIEvent?)
        {
            self.view.endEditing(true)
        }
    
  2. to put textField.resignFirstResponder() to the textFieldDidEndEditing(). I know I don’t want the keyboard to be dismissed when a user edit the second textfield by I tried just to check if it works.

  3. There is a solution how to dismiss keyboard on touch to the tableview background. But actually I do not need keyboard to be dismissed cause the user continue editing another textfields. Dismiss keyboard by touching background of UITableView

[The first tap on the second textfield doesn't show cursor][2] [2]: https://i.sstatic.net/A4voz.png [The second tap on the second textfield shows cursor][3] [3]: https://i.sstatic.net/l82A5.png

Upvotes: 4

Views: 864

Answers (1)

Dmitrii Molev
Dmitrii Molev

Reputation: 103

I figured out the solution.

In textFieldDidEndEditing() function I had tableView.reloadData(). So the sequence of operations was the following:

  1. A user touches textfield1 and does editing. The following functions are fired behind the curtain for the textfield1: textFieldShouldBeginEditing() > textFieldDidBeginEditing()
  2. A user touches textfield2. The following functions are fired behind the curtain:

    for the textfield1: textFieldShouldEndEditing() > textFieldDidEndEditing() > tableView.reloadData()

    for the textfield2: textFieldShouldBeginEditing()

The fact that tableView.reloadData() was run in textFieldDidEndEditing() of the textfield1 was the reason why textFieldDidBeginEditing() of the textfield2 was not fired and editing session has not been started. TableView.reloadData() launches resignFirstresponder().

To overcome this behavior your need to make textField2 becomeFirstresponder before TableView.reloadData() and after. Here is the code

    textField2.becomeFirstResponder()
    tableView.reloadData()

    let delayInSeconds = 0.1

    let popTime : dispatch_time_t = dispatch_time(DISPATCH_TIME_NOW, Int64(delayInSeconds * Double(NSEC_PER_SEC)))
    dispatch_after(popTime, dispatch_get_main_queue(),
        {
            nextTextField.becomeFirstResponder()
        })

Here is the answer that helped me https://stackoverflow.com/a/16462473/5826451

Upvotes: 4

Related Questions