Swift: Become First Responder on UITextField Not Working? - ios

I've created a custom UIViewController with one UITextField on Storyboard. On viewDidLoad, I set the UITextFIeld to becomeFirstResponder, nothing happened (no keyboards popped up).
I then tried calling resignFirstResponder(), but it returned false. Next I tried to find who the first responder is through looping all the subviews using the code over # Get the current first responder without using a private API. It turns out none of the sub views are the first responder.
My ViewController in storyboard
My Code
class BLTestViewController: UIViewController, UITextFieldDelegate {
#IBOutlet var tf: UITextField
override func viewDidLoad() {
super.viewDidLoad()
tf.delegate = self
tf.becomeFirstResponder()
// Do any additional setup after loading the view.
}
}
As simple as it gets...WHY ISN'T THE KEYBOARD COMING UP!!! One thing I do have on is auto layout, but I'm not sure if that affects the keyboard popping up.

Swift 4 it worked for me
try it
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
textView.becomeFirstResponder()
}

I just tested it with a textfield by calling self.tf.becomeFirstResponder() indside viewDidLoad() function and its working absolutely fine. You'll need to toggle your keyboard by pressing command + K as nflacco just pointed out and disable the hardware keyboard in the simulator as:
iOS Simulator -> Hardware -> Keyboard
Uncheck "Connect Hardware Keyboard"

I think
class BLTestViewController: UIViewController, UITextFieldDelegate {
#IBOutlet var tf: UITextField
override func viewDidLoad() {
super.viewDidLoad()
tf.delegate = self
self.focustf()
// Do any additional setup after loading the view.
}
func focustf(){
self.tf.becomeFirstResponder()
}
}

Swift 4 and iOS 11
In my case, no mater what I tried, I was not able to set first responder until I tried this.
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
if cell.isKind(of: YOURTABLEVIEWCELL.self) {
if let yourCell = cell as? YOURTABLEVIEWCELL{
yourCell.yourUiTextField.becomeFirstResponder()
}
}
}
Hope this helps someone stuck with the same problem.

Try setting it after a delay:
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
textField.becomeFirstResponder()
}
sometimes the wrong is the time in render the view

If you are using the iOS Simulator, press ⌘ command + shift + K to open the keyboard.

Related

Swift App Xib - Second ViewController - Labels not showing for 30 seconds but Buttons etc are. How can I solve?

Swift App Xib - Second ViewController - Labels not showing for 30 seconds but Buttons and other controls showing immediately. What could this be / how can I solve this?
Xcode 7.3.1
Swift 2
This is happening on the device and in the simulator
---> Video of Issue <-----
I present from first viewController like this:
secondViewController.user = user
self.presentViewController(secondViewController, animated: true, completion: nil)
Second View Controller
override func viewDidLoad() {
super.viewDidLoad()
print("ViewController did load")
print("selected facility is: ", user?.selectedFacility)
// Do any additional setup after loading the view.
}
// required init(coder aDecoder: NSCoder) {
// super.init(nibName: "ListViewController", bundle: NSBundle.mainBundle())
// }
override func awakeFromNib() {
print("awake from nib")
}
override func viewWillAppear(animated: Bool) {
print("viewWillAppear")
}
override func viewDidAppear(animated: Bool) {
print("viewDidAppear")
}
override func viewDidDisappear(animated: Bool) {
print("viewDidDisappear")
}
UPDATE
If I set the text in viewDidLoad the label appears at the same time as everything else.
override func viewDidLoad() {
super.viewDidLoad()
print("ListViewController did load")
labelX.text = "heyVC"
Adding the outlet itself didn't change anything. It was actually programmatically setting the text that fixed it. I think this is a bug in IB. I will file with apple.
Bug number is 27029176
See if you have set some custom font of label and the font file could not be found by system(like if you have deleted the file). If system font is not set in Label , try setting system font and re-run to confirm.
Are you doing anything with NSURL / NSMutableURLRequest / dataTaskWithRequest?
I am experiencing exactly the same thing with the 30sec delay. When I am commenting out my code which is fetching data from an URL (with the above mentioned methods) the labels are showing instantly. When the code is executed, the labels are displayed with a delay. I guess the fetching somehow makes things asynchronous.
Not exactly a solution but maybe a starting point for further research. Please let me/us know if you have new ideas or the solution. Thanks. :-)

Avoid keyboard closing when iPhone rotated XCode Swift

I have in left navigation item UITextField. When I type something in there and rotate device, keyboard hides everytime.
I tried to handle UIKeyboardWillHideNotification, but all what I got is: keyboard closes and shows again after that. It's not good, I need to rotate keyboard along with view...
Please help in Swift 2.
Okay, I found the solution!
First, need to implement delegate:
ViewController: UIViewController, UITextFieldDelegate
Next, add to viewDidLoad method:
override func viewDidLoad() {
super.viewDidLoad()
textField.delegate = self
}
To the end, realise textFieldShouldEndEditing function:
func textFieldShouldEndEditing(textField: UITextField) -> Bool {
//here we can add some if-block for orientation change or smth else
return false
}
override func willRotateToInterfaceOrientation(toInterfaceOrientation: UIInterfaceOrientation, duration: NSTimeInterval) {
textField.becomeFirstResponder()
}
The method above here gets called when the device will rotate, as you don't care about the orientation we don't check it and simple instruct the textfield you are editing to become first responder.

Hide keyboard on tap on each view - Swift

I'm not going to ask how to hide the keyboard after you are done with editing a textField. My question is : Is there a way to do this on each view ? (like a setting) or do I need to write the two following functions and set the delegate properly every time ?
func textFieldShouldReturn(textField: UITextField) -> Bool // called when 'return' key pressed. return NO to ignore.
{
textField.resignFirstResponder()
return true;
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
self.view.endEditing(true)
}
I'm developing an app with a lot of textfields (and also views) so I try to avoid redundance code. What is the best solution to avoid this repetition?
Thank you!
You can create your own text field, which is subclass of UITextField. See the simple custom UITextField below:
import UIKit
class CustomTextField: UITextField, UITextFieldDelegate {
override func awakeFromNib() {
super.awakeFromNib()
self.delegate = self
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
self.resignFirstResponder()
return true
}
}
Use your custom text field name to Custom Class in your Storyboard.
See my example at Github
The easiest thing to do, is put one giant invisible button the size of the screen underneath your text fields, then when a non text field is tapped, you call the invisible button action to close it. If this does not apply in your scenario please let me know.
Create an IBAction method to dismiss keyboard
#IBAction func backgroundTapped (sender: UIView)
{
sender.endEditing(true)
}
Change the class of your UIView to UIControl which contains the textfields in storyboard (You can even do that to your view of the viewcontroller as shown)
It looks like this:
Now you can connect the IBAction to the Touch Up Inside event of this view, in the storyboard, as shown.

iOS 9/Swift 2 input from numpad can't find keyplane

I have some very basic code which reads the text from a textfield when the user presses a button, and updates the text on a label. I have the type of the input field set to number pad.
import UIKit
class ViewController: UIViewController {
#IBOutlet var userGuessTextField: UITextField!
#IBOutlet var resultLabel: UILabel!
#IBAction func guess(sender: AnyObject) {
let randomNumber = String(arc4random_uniform(11))
if randomNumber == userGuessTextField.text {
resultLabel.text = "You're right"
} else {
resultLabel.text = "Wrong! It was a \(randomNumber)"
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
When I trigger my action, xCode throws this error:
Can't find keyplane that supports type 4 for keyboard
iPhone-PortraitTruffle-NumberPad; using
675849259_PortraitTruffle_iPhone-Simple-Pad_Default
EDIT:
Turns out this is not an error at all, but a simple logging statement. I must have accidentally set a breakpoint in my action, giving it the look and feel of a crash. Thank you, first responder.
Laugh uncontrollably and just keep going. It's not an error. It's just a bit of fluff dropped into the console. Ignore it.
It can happened sometime when you update xocode testing on Simulator you can try this fix:
iOS Simulator -> Hardware -> Keyboard -> Connect Hardware Keyboard
This is not an error. It just says cannot find keyplane..
You can switch to simulator keyboard from Hardware -> Keyboard -> Toggle Software Keyboard or simply press cmd + shift + k
You can even ignore this ;-)

How to dismiss keyboard with multiple UITextField

I'm a noob here and in iOS world. I am having trouble dismiss keyboard on a specific case in my very simple todo list iOS app.
I'd like the keyboard to get dismiss when user taps anywhere outside the current text field or the keyboard itself. So far, I got the keyboard dismisses just fine (thanks to you guys here in stack overflow) when user taps on the UITableView, or most element on my app. HOWEVER, when user taps on another UITextField, the keyboard does not go away.
FYI, here's the list of existing threads I researched so far but have yet to solve this issue.
1) How to dismiss keyboard iOS programmatically
2) Resigning First Responder for multiple UITextFields
3) Dismissing the First Responder/Keyboard with multiple Textfields
4) (a few more at least but I lost track :( )
Here's what I did so far:
(in viewDidLoad())
// Add 'tap' gesture to dismiss keyboard when done adding/editing to-do item
var tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "tapOutside:")
tap.cancelsTouchesInView = true
self.view.addGestureRecognizer(tap)
func tapOutside(tapOutside: UIGestureRecognizer) {
// Dismiss keyboard
self.view.endEditing(true)
}
#IBAction func EditingDidBegin(sender: UITextField) {
// Highlight the text field which user is editing
self.highlightTextField(sender, highlight: true)
}
#IBAction func EditingDidEnd(sender: UITextField) {
// Undo text field highlight
self.highlightTextField(sender, highlight: false)
self.view.endEditing(true) // try this option and not working
self.setEditing(false, animated: true) // try this option and not working
sender.resignFirstResponder() // try this option and not working
UIApplication.sharedApplication().becomeFirstResponder() // try this option and not working
... // below is my code to update the todo item
}
I also tried to print out all subviews.isFirstResponder() of my view. All of it return false. I also tried override touchesBegan of my UIViewController, and inside it just calls self.view.endEditing(true) and call its super's. This also does not work.
Please help. :(
TIA!
UPDATE:
You guys are awesome! :D I got it working now thanks to you guys. There were several mistakes / messed up as I'm learning new framework. So here's what I did.
1) I did not set UITextField delegate correctly.
Mistake: I ctrl-draged textfield in xcode and link my viewController as delegate and thought that should work out. I will still need to research and understand better why.
Solution: I removed that ctrl-drag link and explicitly call myTextField.delegate = self in tableView:cellForRowAtIndexPath. And that did it. Thanks #Sidewalker
2) Mistake: I have a mixed of textFieldShouldBeginEditing, etc. and #IBAction func EditingDidBegin. So I got myself into the situation where textFieldShouldBeginEditing got the call, but EditingDidBegin did not get call.
Solution: Once I set the delegate = self explicitly and stick with implementing textField... methods and not use any #IBAction for textField, things just work.
Here's one option... We're going to add a boolean flag to determine whether or not we're in a textField when an edit attempt for another textField begins
Make your class adhere to UITextFieldDelegate
class MyClass: UIViewController, UITextFieldDelegate
Don't forget to set the delegate, we'll add the flag as well
myTextField.delegate = self
var inField = false
Implement "textFieldShouldBeginEditing" and "textFieldDidBeginEditing"
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
if inField {
inField = false
return false
}
return true
}
func textFieldDidBeginEditing(textField: UITextField) {
inField = true
}
I prefer tracking things like this rather than identifying subviews as it allows the flag to be utilized elsewhere and cuts down code complexity.
Well the keyboard isn't going away because it doesn't expect to have to. The new UITextField is just becoming the first responder while the other resigns. If you don't want a textField to become the first responder if another is already, you're going to have to cut it off before it gets the chance to. I would try to implement textFieldShouldBeginEditing and figuring out the logic there.
I'm not in love with the way this looks but this should do something along those lines.
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
for subView in self.view.subviews{
if(subView.isKindOfClass(UITextField)){
if(subView.isFirstResponder()){
subView.resignFirstResponder();
return false;
}
}
}
return true;
}
First set all the UITextField (your are creating) delegate as self and create one UITextField member variable. Now implement "textFieldDidBeginEditing" delegate method and assign the textfield to your member UITextField variable. As given below
func textFieldDidBeginEditing(textField: UITextField) {
yourMemberVariable = textField;
}
So now whenever you want to dismiss the keyboard call the dismiss method on "yourMemberVariable" object. It should work !!
What I usually do is implementing this two method:
The first one add a UITapGestureRecognizer to the whole UIViewController view
func hideKeyboard() {
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))
view.addGestureRecognizer(tap)
}
The second one just get called every time the user touch anywhere on the UIViewController's view
func dismissKeyboard() {
self.view.resignFirstResponder()
}
I add the first one to the viewDidLoad method of the UIViewController. Or better yet if you want to use that on all the app just make that an extension for your UIViewController.
How about doing this in viewController, It works for me
func dismissKeyboard() {
//All the textFields in the form
let textFields = [textField1, textField2, textField3, textField4, textField5]
let firstResponder = textFields.first(where: {$0.isFirstResponder ?? false })
firstResponder?.resignFirstResponder()
}

Resources