I'm trying to show changes made to a UITextField on a separate UILabel. Is there a way to capture full text of the UITextField after each character the user types in? Currently I'm using this method, but it does not capture the last character that the user has entered.
I know that UITextView has "didChange" method, but I could not find that method for a UITextField.
//does not capture the last character
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
[self updateTextLabelsWithText: textField.text];
return YES;
}
How can I take text out of UITextField after each character entered?
Thank you!
First add one UITextField and UILabel to storyboard / nib
Now assign IBOutlet for UILabel (Here I have used myLabel)
Assign UITextFieldDelegate to file owner, also implement the same delegate in .h file
Use these lines of code:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
[self updateTextLabelsWithText: newString];
return YES;
}
-(void)updateTextLabelsWithText:(NSString *)string
{
[myLabel setText:string];
}
Simply handle the "Editing Changed" event
[textField addTarget:self
action:#selector(editingChanged:)
forControlEvents:UIControlEventEditingChanged];
and the selector:
-(void) editingChanged:(id)sender {
// your code
}
You can do this manually, or with the storyboard by CTRL-Dragging the "Editing changed" Sent event to your .h, creating the editingChanged method for you.
Swift with addTarget Swift 2.0+
titleTextField.addTarget(self, action: #selector(textFieldTyping), forControlEvents: .EditingChanged)
And implement selector
func textFieldTyping(textField:UITextField)
{
//Typing
}
In Swift 2.0+
class CheckInViewController: UIViewController, UITextFieldDelegate {
override func viewDidLoad() {
super.viewDidLoad()
yourTextField.delegate = self
}
func textField(textField: UITextField!, shouldChangeCharactersInRange range: NSRange, replacementString string: String!) -> Bool {
var updatedTextString : NSString = textField.text as NSString
updatedTextString = updatedTextString.stringByReplacingCharactersInRange(range, withString: string)
self.methodYouWantToCallWithUpdatedString(updatedTextString)
return true
}
}
Hope it helps you swift pioneers
In Swift 3.0:
Some of these solutions were one character behind, or for earlier versions of Swift and Obj-C. Here is what I am using for Swift 3.0
In the class I declared a placeholder to store the text.
var tempName = ""
In ViewDidLoad I used:
nameField.addTarget(self, action: #selector(typingName), for: .editingChanged)
Then I made a function called:
func typingName(textField:UITextField){
if let typedText = textField.text {
tempName = typedText
print(tempName)
}
}
Swift 3.0+: This worked very nicely for me.
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
self.yourLabel.text = "\(textField.text ?? "")\(string)"
return true
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if textField == yourTextFieldOutletName
{
if yourTextFieldOutletName.isEmpty == false
{
youtlabelname.text = yourTextFieldOutletName.text!
}
}
return true
}
func textViewDidEndEditing(_ textView: UITextView) {
if textField == yourTextFieldOutletName
{
if yourTextFieldOutletName.isEmpty == false
{
youtlabelname.text = yourTextFieldOutletName.text!
}
}
}
Related
I would like to use the
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
}
I'm fetching a number from firebase which will be the maximum they will be allowed to type into a textfield. Fetching the number is easy, how do I set this maximum for the UITextField?
Just make a class and fill maximum number in storyboard as like:
import UIKit
#IBDesignable
class CustomTextField: UITextField {
#IBInspectable var maxLength: Int = Int.max {
didSet {
addTarget(self, action: #selector(limitLength), for: .editingChanged)
}
}
override func didMoveToWindow() {
super.didMoveToWindow()
addTarget(self, action: #selector(limitLength), for: .editingChanged)
}
#objc private func limitLength() {
guard let prospectiveText = text, prospectiveText.count > maxLength else {
return
}
let selection = selectedTextRange
text = String(prospectiveText.prefix(maxLength))
selectedTextRange = selection
}
}
you can use textField value;
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if textField.text.count <= maximumNumberOfCharachters {
...
}
return false
}
How to limit the few specific text field only allow to insert int?
not all text fields. only a few specific ones.
Thank you.
Try this one.
class ViewController: UIViewController,UITextFieldDelegate {
#IBOutlet var yourTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
yourTextField.delegate = self
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
//For mobile numer validation
if textField == yourTextField {
//Add specific int numbers
let allowedCharacters = CharacterSet(charactersIn:"0123 ")//Here change this characters based on your requirement
let characterSet = CharacterSet(charactersIn: string)
return allowedCharacters.isSuperset(of: characterSet)
}
return true
}
}
Tried setting your textField's keyboard type?
yourTextField.keyboardType = .numberPad
Can also look into the delegate method
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
return true
}
You can from there add logic to return true or false if the textField's selection meets your requirements
My swift code below goal is when the user enters something into textfield tt it reflects it in currentPageLabel. The func that I thought would do this is having no effect. Nothing I enter into the textfield displays on the label. All of my code does not use a storyboard.
var currentPageLabel = UILabel()
var tt = UITextfield()
func textFieldDidBeginEditing(_ textField: UITextField) {
currentPageLabel.text = tt.text
}
Try this UITextFieldDelegate method:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let text = (textField.text as NSString?)?.replacingCharacters(in: range, with: string)
currentPageLabel.text = text
return true
}
You can use addTarget feature in this case! Just add target to your textField in viewDidload method, and add selector method marked with #objc textFieldDidChange. Inside textFieldDidChange function set text to your label!
textfield.addTarget(self, action: #selector(textFieldDidChange), for: .editingChanged)
#objc func textFieldDidChange(_ textField: UITextField) {
currentPageLabel.text = textField.text
}
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 ...
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 = #"";