I have a couple of UITextField's and one UIButton. If I tap on the UIButton, I want to place some static text in the active UITextField.
So something like:
#IBAction func buttonEen(sender: UIButton) {
'active textField'.text = "static text"
}
But how do I determine which UITextField is the active UITextField and how do I reach it?
To write text in last active UITextField you have to make your UIViewController a delegate of UITextField
ex:
class ViewController: UIViewController, UITextFieldDelegate
declare a activeField variable
ex:
var activeField: UITextField?
then implements textFieldDidBeginEditing
ex:
func textFieldDidBeginEditing(textField: UITextField)
{
activeField = textField
}
So your button function will be something like
#IBAction func buttonEen(sender: UIButton) {
if activeField
{
activeField.text = "static text"
}
}
First you need to create your textfield delegate (probably in 'ViewDidLoad()') :
activeTxtField.delegate = self
Then you need to implement the textField delegate function:
extension 'YourVC': UITextFieldDelegate {
func textFieldDidBeginEditing(_ textField: UITextField) {
if textField == activeTxtField {
// Do whatever you want
// e.g set textField text to "static text"
}
}
}
Related
I am trying to have my inputs inside of my UITextField show up in the debugger console, when I am typing in the created TextField however the Delegate Methods don't seem to be responding. I am expecting to see my print statement that are seen below for my UIdelegate methods, like when I first started typing, while I type, and when I press the 'return key'. All delegate methods do not seem to be activated, and I am not sure how to make my Textfield link to the delegate method directly. In addition, I have another UITextField (Not shown here), would I have to 'addTarget' to differentiate between the two?
class ViewController: UIViewController, UITextFieldDelegate {
let createUserName: UITextField = {
var myTextField = UITextField ()
myTextField.translatesAutoresizingMaskIntoConstraints = false
myTextField.placeholder = "Username" //set placeholder text
myTextField.font = UIFont.systemFont(ofSize: 14) // set font size of text field
myTextField.layer.borderWidth = 1.0 //set width
myTextField.layer.borderColor = UIColor.red.cgColor//set background color to a ui color
myTextField.layer.backgroundColor = UIColor.white.cgColor
myTextField.layer.cornerRadius = myTextField.frame.height/2
myTextField.autocorrectionType = .no // disable autocorrect when typing for .no, enable with .yes
myTextField.isSecureTextEntry = false// masked text
myTextField.keyboardType = .default //keyboard style is set to default
myTextField.returnKeyType = .default //retuen key text changed to "Done" instead of return
myTextField.clearButtonMode = .whileEditing
myTextField.delegate = self as? UITextFieldDelegate
return myTextField
}()
override func viewDidLoad() {
super.viewDidLoad()
createUserName.delegate = self
view.addSubview(createUserName)
setupUserName()
}
//UITextField Delegate methods
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
print("textfield should begin editting")
return true
}
func textFieldDidBeginEditing(_ textField: UITextField) {
print("text field edit")
}
//see string that is typed in debugger for use to validate password and crossreference username
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if let textFieldString = textField.text, let swtRange = Range(range, in: textFieldString) {
let fullString = textFieldString.replacingCharacters(in: swtRange, with: string)
print("FullString: \(fullString)")
}
return true
}
//dismiss keyboard when return button is pressed
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
print("text field return")
return true
}
}
Your viewController should inherit from UITextFieldDelegate
class YourViewController : UIViewController, UITextFieldDelegate {
// your code
}
Also in your ViewDidLoad, move your createUsername.delegate = self to last line.
That string:
myTextField.delegate = self as? UITextFieldDelegate
tell us that your VC don't directly conform protocol UITextFieldDelegate...
If you conformed swift doesn't add as? cast ...
I have an addTarget set up on UITextField that clears the placeholder text when editingDidBegin. But I don't know how to restore the placeholder text if the user clicks on another UITextField, or the field is left empty.
This is located in viewDidLoad()
firstInitialTextField.addTarget(self, action: #selector(clearPlaceholderInTextField), for: UIControl.Event.editingDidBegin)
This function is located in the main body of the program.
#objc func clearPlaceholderInTextField() {
firstInitialTextField.placeholder = ""
}
I have several fields I would like to apply this same functionality to.
Create outlet collection for all the textfields like
#IBOutlet var textFs:[UITextField]!
with different tag for each , And array of placeHolders that you set in viewDidLoad
var placeholders = [String]()
Then set the vc as the delegate for all of them in viewDidLoad
textFs.forEach { $0.delegate = self }
Implement
func textFieldDidBeginEditing(_ textField: UITextField) {
textField.placeholder = ""
}
func textFieldDidEndEditing(_ textField: UITextField) {
textField.placeholder = placeholders[textField.tag]
}
I have SequencedTextFields protocol, which contains sequence of text fields. When user taps Return button on keyboard, current text field should resign first responder and next text field in the sequence should become first responder. And it works good, when I'm using direct implementation of UITextFieldDelegate protocol for view controller:
extension MyViewController: UITextFieldDelegate {
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
nextInSequence(after: textField)?.becomeFirstResponder()
return true
}
}
But, when I'm trying to use default implementation, it does not triggers ever:
extension UITextFieldDelegate where Self: SequencedTextFields {
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
nextInSequence(after: textField)?.becomeFirstResponder()
return true
}
}
What could be the reason? Or I've missed something?
UPDATE:
My view controller defining:
final class MyViewController: UIViewController, UITextFieldDelegate, SequencedTextFields
Setting up the delegate for the text fields:
The reason why your implementation is not working is because you are trying to extend an interface (UITextFieldDelegate) instead of a class, that's why it works when you use UIViewController instead.
What you can do is to create a custom class SequencedTextField that extends UITextField. Add a custom delegate (that I called sequencedDelegate that represents the class that implements your SequencedTextFields protocol.
Extend SequencedTextField to implement UITextFieldDelegate with your default implementation.
On MyViewController, set up your SequencedTextField delegate with the viewController itself.
At the end it should look something like this:
protocol SequencedTextFields: class {
func nextInSequence(after: UITextField) -> UITextField?
}
class SequencedTextField: UITextField {
weak var sequencedDelegate: SequencedTextFields?
}
extension SequencedTextField: UITextFieldDelegate {
public func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
sequencedDelegate?.nextInSequence(after: textField)?.becomeFirstResponder()
return true
}
}
class MyViewController : UIViewController, SequencedTextFields {
var textField = SequencedTextField()
override func viewDidLoad() {
super.viewDidLoad()
textField.delegate = textField
textField.sequencedDelegate = self
}
func nextInSequence(after: UITextField) -> UITextField? {
// your view controllers nextInSequence implementation here
}
}
What is wrong with your code?
The first extension is the extension of your view controller MyViewController, that's why it is working. But the second one is the extension of UITextFieldDelegate. Those are completely two different things.
Not clear what you want to achieve.
This is how you can use your custom protocol
If you want to make one CustomProtocol for your special UITextField you can do like this.
CustomTextFieldProtocol
Declear the protocol
protocol SequencedTextFields: UITextFieldDelegate {
func checkSomeThing(_ textField: UITextField) -> Bool
}
Set the delegate
self.textField.delegate = self
ViewController Extension to implement your Delegate methods
extension ViewController: SequencedTextFields {
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
nextInSequence(after: textField)?.becomeFirstResponder()
return true
}
func checkSomeThing(_ textField: UITextField) -> Bool {
print("Check here")
return true
}
}
I have a textfield in each cell of my tableview. I want to quit keyboard when users pressed on the return key. I tried:
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
But it doesn't work and I can't seem to find a away to reference the textfield inside the cell of my tableview. Please help, thanks!
I assume that you have created IBOutlets of your textfield in your cell class.
Give your textfield delegate to self in cellForRow datasource method of UITableView
cell.yourTextField.delegate = self
You can give delegate form storyboard.
You should let your custom UITableViewCell class to confirms to UITextFieldDelegate:
class TableViewCell: UITableViewCell, UITextFieldDelegate {
// ...
}
In awakeFromNib you should your textfields delegate to the cell class:
override func awakeFromNib() {
// ...
textField.delegate = self
// ...
}
Finally, implement textFieldShouldReturn:
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
Hope that helped.
In Xcode4 I've created some placeholder text for a UITextField and I'd like it to clear when the user taps in the box.
So, in the Attributes Inspector for the text field I've clicked "Clear when editing begins" however this does not immediately remove the text when I tap in the text box (it only disappears when you start typing).
Is there any way of removing the placeholder text immediately on tapping in the text box?
make your ViewController the delegate of the textField and implement those two methods:
- (void)textFieldDidBeginEditing:(UITextField *)textField {
textField.placeholder = nil;
}
- (void)textFieldDidEndEditing:(UITextField *)textField {
textField.placeholder = #"Your Placeholdertext";
}
The solution provided by Matthias Bauch works well, but what happens when you have more than one UITextField to worry about? Now you have to identify which UITextField is referred to in textFieldDidEndEditing:textField (possibly by use of the tag property), and that results in more unnecessary code and logic.
A much simpler solution: simply assign a clear color to the placeholder text , and when done editing, revert back to it's original color. This way, your textFieldDidEndEditing:textField doesn't have to identify the textField to set back its corresponding text after it was nullified as in Bauch's solution.
- (void)textFieldDidBeginEditing:(UITextField *)textField {
[textField setValue:[UIColor clearColor] forKeyPath:#"_placeholderLabel.textColor"];
}
- (void)textFieldDidEndEditing:(UITextField *)textField {
[textField setValue:[UIColor placeholderColor] forKeyPath:#"_placeholderLabel.textColor"];
}
You should also check if text filed is empty then you should put place holder again
- (void)textFieldDidBeginEditing:(UITextField *)textField {
textField.placeholder = nil;
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
if ([textField.text isEqualToString:#""] || [[textField.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length] == 0))
{
[textField setText:#""];
textField.placeholder = #"Your Placeholdertext";
}
}
use this..
- (void)textFieldDidBeginEditing:(UITextField *)textField{
textField.placeholder=nil;
}
don't forget to add the delegate for the textfield to your file Owner.
If you have more than one TextField
1) Add String variable to your class
class YourViewController : UIViewController {
var placeHolder = ""
2) Add UITextFieldDelegate
extension YourViewController : UITextFieldDelegate {
func textFieldDidBeginEditing(_ textField: UITextField) {
placeHolder = textField.placeholder ?? ""
textField.placeholder = ""
}
func textFieldDidEndEditing(_ textField: UITextField) {
if textField.placeholder == ""{
textField.placeholder = placeHolder
}
}
In your .h file declare a function like
-(IBAction)clear:(id)sender;
attach this function to your touchdown event of your UITextField.
in your .m file
-(IBAction)clear:(id)sender
{
myplaceHolderText.text=#"";
}
- (void)textFieldDidBeginEditing:(UITextField *)textField{
textField.placeholder=nil;
}
textfield delegate make place holder value to nil
The #etayluz 's solution is better (my opinion), because you don't need to worry about assigning placeholder'a text again.
If you have custom textFields in different places of your app and want them to behave equally (as I need in my case) you can add this code to your custom TextField's class:
class CustomTextField: UITextField, UITextFieldDelegate {
private func setup() {
//do additional setup like attributedPlaceholder, inset, etc.
self.delegate = self
}
override func awakeFromNib() {
super.awakeFromNib()
setup()
}
// MARK: UITextFieldDelegate methods
func textFieldDidBeginEditing(textField: UITextField) {
textField.setValue(UIColor.clearColor(), forKeyPath: "_placeholderLabel.textColor")
}
func textFieldDidEndEditing(textField: UITextField) {
textField.setValue(UIColor.lightGrayColor(), forKeyPath: "_placeholderLabel.textColor")
}
}
But if you need to have specific UITextFieldDelegate's methods for individual textField you DO need to implement this logic for it individually:
class LoginViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var emailTextField: CustomTextField!
#IBOutlet weak var passwordTextField: CustomTextField!
override func viewDidLoad() {
super.viewDidLoad()
textFields = [emailTextField, passwordTextField]
for textField in textFields {
textField.delegate = self
}
// MARK: UITextFieldDelegate methods
func textFieldDidBeginEditing(textField: UITextField) {
textField.setValue(UIColor.clearColor(), forKeyPath: "_placeholderLabel.textColor")
}
func textFieldDidEndEditing(textField: UITextField) {
textField.setValue(UIColor.lightGrayColor(), forKeyPath: "_placeholderLabel.textColor")
}
}
In case of SWIFT 3 or later
func textFieldDidBeginEditing(_ textField: UITextField) {
textField.placeholder = nil
}
func textFieldDidEndEditing(_ textField: UITextField) {
textField.placeholder = "Text Placeholder"
}
On Button action Event put this Code:
txtName.placeholder = #"";