Reputation: 103
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:
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)
}
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.
[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
Reputation: 103
I figured out the solution.
In textFieldDidEndEditing()
function I had tableView.reloadData()
. So the sequence of operations was the following:
textFieldShouldBeginEditing()
> textFieldDidBeginEditing()
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