Reputation: 167
How to focus activated UITextField with UIResponder?
Code below:
// customTextField.swift
import UIKit
class customTextField: UITextField {
override func becomeFirstResponder() -> Bool {
if self.tag == 1 {
self.borderStyle = .Line
self.superview?.viewWithTag(2)?.resignFirstResponder()
self.superview?.viewWithTag(3)?.resignFirstResponder()
} else if self.tag == 2 {
self.borderStyle = .Line
self.superview?.viewWithTag(1)?.resignFirstResponder()
self.superview?.viewWithTag(3)?.resignFirstResponder()
} else {
self.borderStyle = .Line
self.superview?.viewWithTag(1)?.resignFirstResponder()
self.superview?.viewWithTag(2)?.resignFirstResponder()
}
return true
}
override func resignFirstResponder() -> Bool {
print("This is called")
self.borderStyle = .None
super.resignFirstResponder()
return true
}}
I would like to check which textfield is the firstResponder through View's tag. And then if other TextField should be unfocused by resignFirstResponder.
But, the resignFirstResponder
within the becomefirstResponder's code block isn't even called when I touch a textField in the view.
Upvotes: 3
Views: 3653
Reputation: 48514
Do not break the superclass: Pass messages along
In the process of overwriting system messages, like becomeFirstResponder
, you may inadvertently disable the parent class. The safest, no-op becomeFirstResponder
is this:
override func becomeFirstResponder() -> Bool {
return super.becomeFirstResponder()
}
Omitting super.becomeFirstResponder()
will compromise UITextField
.
Also let the original logic (when to become or not become a responder) take its course. Always responding true
or false
changes the behavior of the parent class, which may have unwanted and unfortunate side effects.
override func becomeFirstResponder() -> Bool {
let becomeFirstResponder = super.becomeFirstResponder()
// Do stuff
return becomeFirstResponder
}
Do not replicate the OS
No need to keep track of the current responder.
Let the OS message you of who is the responder: attempting to do the tracking otherwise may actually not work when the onscreen keyboard gets dismissed without a new field being tapped, and is bound to break. Instead, listen to resignFirstResponder
in the same manner:
override func resignFirstResponder() -> Bool {
return super.resignFirstResponder()
}
Less code, more flexibility
Putting both rules together, and using .RoundedRect
& .Line
for an explicit redraw (.None
has no effect), your entire CustomTextField
could look like so:
class CustomTextField: UITextField {
override func becomeFirstResponder() -> Bool {
let becomeFirstResponder = super.becomeFirstResponder()
if becomeFirstResponder {
self.borderStyle = .line
}
return becomeFirstResponder
}
override func resignFirstResponder() -> Bool {
let resignFirstResponder = super.resignFirstResponder()
if resignFirstResponder {
self.borderStyle = .roundedRect
}
return resignFirstResponder
}
}
Notice that no action is taken if super.becomeFirstResponder()
or super.resignFirstResponder()
did not succeed.
Demo
► Find this solution on GitHub and additional details on Swift Recipes.
Upvotes: 8