Dismiss keyboard after a user entered 11 digit [duplicate] - ios

This question already has answers here:
How to do a live UITextField count while typing (Swift)?
(12 answers)
Closed 4 years ago.
I've been looking for a solution in the site to dismiss keyboard after a user entered 11 digits. I found a Solution here, but it is an Objective-c and I'm looking for a swift code, can anybody help?

This is how it works
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
// YOU SHOULD FIRST CHECK FOR THE BACKSPACE. IF BACKSPACE IS PRESSED ALLOW IT
if string == "" {
return true
}
if let characterCount = textField.text?.count {
// CHECK FOR CHARACTER COUNT IN TEXT FIELD
if characterCount >= 11 {
// RESIGN FIRST RERSPONDER TO HIDE KEYBOARD
return textField.resignFirstResponder()
}
}
return true
}
EDIT
1) You should set the IBOutlet to your textField
2) Set delegate to self, on your textField.
3) YourViewController: UIViewController, UITextFieldDelegate { }
4) Implement the delegate method as in above. check for the backspace and allow if user enters backspace to remove characters from textField.

you may try this :
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let count: Int = textField.text?.count ?? 0
if count >= 11 {
textField.resignFirstResponder()
}
return true
}

Related

Swift prevent "0" being first character for 1 specific uiTextField

so i search online about how "func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool" for formating textField. i found this way to prevent "0" as my first char in my textfield. it works but, actually not the way i wanted.
The thing is, in my register view theres 4 uiTextfield, which contain :
Name
Phone Number
Pin
Confirm Pin
i only want to prevent "0" as my first char only for my PhoneNum TextField. but with this code, i kinda put all of those 4 textField into prevent "0" as the first char.
here's my code :
#IBOutlet weak var textFullName: SkyFloatingLabelTextField!
#IBOutlet weak var textPhoneNumber: SkyFloatingLabelTextField!
#IBOutlet weak var textPIN: SkyFloatingLabelTextField!
#IBOutlet weak var textConfirmPIN: SkyFloatingLabelTextField!
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
// I try this one
if string == "0" {
if textField.text!.count == 0 {
return false
}
}
// i also try to change the "textField" into "textPhoneNumber"
if string == "0" {
if textPhoneNumber.text!.count == 0 {
return false
}
}
// both of those method wont work
return true
}
can someone tell me how to just prevent my textPhoneNumber to cannot type "0" as its first char? with this method i only put all of my textfield into cannot type "0" as its first char.
Thanks guys
The UITextFieldDelegate methods will get called for ALL of the text fields for which the view controller is set up as the delegate.
Presumably your textField(_:shouldChangeCharactersIn:replacementString:) method is being called for all 4 of your SkyFloatingLabelTextField objects (which I assume are a custom subclass of UITextField.)
If you want different behavior for different text fields, you need to write your code to handle each case separately. Something like this:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
switch textField {
case textPhoneNumber:
//Special case code to handle the phone number field
if string == "0" {
if textField.text!.count == 0 {
return false
}
return true
}
case textFullName:
//Special case code to handle the name field (if needed.)
default:
//Shared code to handle the other fields the same way
}
}
You can check if the textField is textPhoneNumber directly by using the equatability == sign.
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if textField == textPhoneNumber {
// do textPhoneNumber stuff
} else {
// others
}
return true
}

Disable UITextField cursor movement after max input

I created a custom UITextField component for a fixed size input. TextField's width, font size, kerning and character count are all fixed. I can block user from entering more than 8 characters (see below shouldChangeCharactersIn method), however after the 8th character, cursor automatically moves to next position, which creates the following problem.
I want to show all the entered characters without decreasing their size. So
[ 1 2 3 4 5 6 7 8 ]
should be shown instead of
[ 2 3 4 5 6 7 8 | ]
I tried to put cursor just right of the 8th character, however this changes the all kerning and effects all of the other characters.
What is the correct way to handle this? How should I prevent the cursor movement, so that UITextField won't scroll right?
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
guard let textFieldText = textField.text,
let rangeOfTextToReplace = Range(range, in: textFieldText),
!string.containsSpecialCharacters else {
return false
}
let substringToReplace = textFieldText[rangeOfTextToReplace]
let count = textFieldText.count - substringToReplace.count + string.count
return count <= 8
}
I solved the problem by changing the kern after the last character. So now, instead of jumping 40pt, cursor jumps only 1pt (or whatever you set on below method)
#objc private func textFieldDidChange() {
guard let text = textField.text else { return }
if text.count == Constant.deviceCodeCharacterCount {
let attributedString = NSMutableAttributedString(string: text)
attributedString.addAttribute(.kern, value: Constant.deviceCodeCharacterSpacing, range: NSRange(location: 0, length: text.count - 1))
attributedString.addAttribute(.kern, value: 1, range: NSRange(location: Constant.deviceCodeCharacterCount - 1, length: 1))
textField.attributedText = attributedString
}
}
try the following code:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if textField.text?.count ?? 0 <= 7{
if textField.text?.count ?? 0 == 7{
DispatchQueue.main.async {
textField.resignFirstResponder()
}
}
return true
}
textField.resignFirstResponder()
return false
}
set your customTextField's delegate to self in your viewController's viewDidLoad method, and confirm to UITextFieldDelegate protocol
What happen if you try this code?
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool
{
if range.location < 8 {
return true
}
// return NO to not change text
return false
}

UITextFields should get active in reverse order

I have six UITextFields one after another which is used for typing passcode.
after one character, next UITextFields becomes active. But how to do for backspace? On keyboard backspace, text field should get active in reverse order
For your requirement, I made a demo and it is working like a charm.
So in order to fulfill your requirement you have to follow below instructions:
Give tag to every UITextField in order like 101,102,103,104,105 and 106
Then make every textField's delegate to self (UIViewController)
Then implement UITextField's below delegate method
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
print("string = \(string) text = \(textField.text)")
if(textField.text?.characters.count == 1){
if string.characters.count == 0{
if textField.tag != 101{
textField.resignFirstResponder()
let preField : UITextField = self.view.viewWithTag(textField.tag-1) as! UITextField
preField.becomeFirstResponder()
}
textField.text = string
return false
}
if textField.tag != 106{
textField.resignFirstResponder()
let nextField : UITextField = self.view.viewWithTag(textField.tag+1) as! UITextField
nextField.text = string
nextField.becomeFirstResponder()
}
return false
}
return true
}

what function can help me to know user input first character in textfield and how to make a blank line when I press keyboard return?

I have two problems.I am a beginner of swift
First,I want to hide the send button until user input frist character.I use textfield delegate functions that they don't implement this idea.
And then, I want to creat a blank line when user input in textfield.I know to use "textFieldShouldReturn" function ,but I use "\n" that it doesn't work for me.How to do this?
this is my code:
func textFieldDidBeginEditing(_ textField: UITextField) {
if textField.text?.isEmpty == false {
aButton.isHidden = true
sendButton.isHidden = false
}
}
update code:
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
self.textField.text = "\n"
return true
}
I also want the textfield change it height.let user can input their message. Does it can be implement?
Or I need to change textfield to textview.
You can use textfields delegate method to check when user start writing something in your textfield.
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool
{
if textField == txtUserName //compare with your textfield object which you have taken by outlet
{
if string.characters.count >= 1 {
//make your button enable
}else
{
// disable your button
}
}
return true
}

Uppercase characters in UItextfield

I have a question about iOS UIKeyboard.
I have a UITextField and I would to have the keyboard with only uppercase characters.
I use a storyboard and I tried to set the Cpitalization as "All characters" to UITextField properties.
But this not solve my problem...any suggestion?
Set your textfield type autocapitalizationType to UITextAutocapitalizationTypeAllCharacters on the UITextField
self.yourTexField.autocapitalizationType = UITextAutocapitalizationTypeAllCharacters;
After call delegate
// delegate method
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSRange lowercaseCharRange = [string rangeOfCharacterFromSet:[NSCharacterSet lowercaseLetterCharacterSet]];
if (lowercaseCharRange.location != NSNotFound) {
textField.text = [textField.text stringByReplacingCharactersInRange:range
withString:[string uppercaseString]];
return NO;
}
return YES;
}
Swift 5.4.2
self.yourTextField.autocapitalizationType = .allCharacters
One issue I have with some of the above answers is if you try and set textfield.text, you will lose the cursor position. So if a user tries to edit the middle of the text, the cursor will jump to the end.
Here is my Swift solution, still using UITextFieldDelegate:
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
if textField == textFieldToUppercase {
if string == "" {
// User presses backspace
textField.deleteBackward()
} else {
// User presses a key or pastes
textField.insertText(string.uppercaseString)
}
// Do not let specified text range to be changed
return false
}
return true
}
For those looking for a Swift version.
Swift 4
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
textField.text = (textField.text! as NSString).replacingCharacters(in: range, with: string.uppercased())
return false
}
Original answer
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
textField.text = (textField.text as NSString).stringByReplacingCharactersInRange(range, withString: string.uppercaseString)
return false
}
Using the Capitalization: All Characters property just forces keyboard to open with caps lock on, but lets the user to turned it off.
The syntax is now
Swift 2
textField.autocapitalizationType = UITextAutocapitalizationType.AllCharacters
Swift 3
textField.autocapitalizationType = .allCharacters
This is a different approach I used, where it does the following:
Enforces capitalization as soon as the character is entered
Catches situations where the user disables caps lock even if it textfield is set to auto caps
Allows for easy editing
Works with Swift 2.2
First, register a notification to be updated whenever any changes occur in the textfield.
textField.addTarget(self, action: #selector(YourClassName.textFieldDidChange(_:)), forControlEvents: UIControlEvents.EditingChanged)
Then, implement textFieldDidChange.
func textFieldDidChange(textField: UITextField) {
textField.text = textField.text?.uppercaseString
}
I chose this to avoid a situation where the user sees an uneven experience of some capitalized, but then changed once they move to the next character.
You should avoid to use delegate method
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool
because this will trigger an unwanted behaviour with iOS 13 + QuickPath typing (the iOS' Swiftkey Keyboard counterpart).
If you swipe on the keyboard and write "hello", it will write "HELLOHELLOHELLOHELLOHELLO" into the textfield. This is because the method is called multiple times and it appends the just changed text via textField.text = uppercasedValue.
The right way is to observe the .editingChange event and uppercase then the value. For example:
func awakeFromNib() {
textField.addTarget(self, action: #selector(textFieldDidChange), for: .editingChanged)
}
and
#objc func textFieldDidChange() {
textField.text = textField.text?.uppercased()
}
Swift 3 / Swift 4 / Swift 5
Just one line code in ViewDidLoad/ViewDidAppear:
If you simply want to see the characters typed regardless of the UPPER/lower case to all CAPITALS/UPPER CASE paste below code either in ViewDidLoad/ViewDidAppear
self.myTextField.autocapitalizationType = .allCharacters
above line changes all letters into CAPITALS while you type automatically
Set UITextField property autocapitalizationType to UITextAutocapitalizationTypeAllCharacters. This will make all characters to appear in upper case. Also visit here to find more about textfields
SwiftUI
For SwiftUI the Syntax for autocapitalization and Keyboard type selection is:
TextField("Your Placeholder", text: $emailAddress)
.keyboardType(.emailAddress)
.autocapitalization(.none)
You can use the following options for autocapitalization:
.none //Specifies that there is no automatic text capitalization.
.words //Specifies automatic capitalization of the first letter of each word.
.sentences //Specifies automatic capitalization of the first letter of each sentence.
.allCharacters //Specifies automatic capitalization of all characters, such as for entry of two-character state abbreviations for the United States.
Swift 4.0 Version:
First set the delegate for the textfield you want to uppercase to the current ViewController (click drag from the textfield to the currentViewController to set the delegate).
After add the extension:
extension CurrentViewController: UITextFieldDelegate{
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
//refference to the textfield you want to target
if textField.tag == 5{
textField.text = (textField.text! as NSString).replacingCharacters(in: range, with: string.uppercased())
return false
}
return true
}
}
You can also use this code.
-(BOOL) textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
// Uppercase for string which you need
textField.text = [textField.text stringByReplacingCharactersInRange:range
withString:[string uppercaseString]];
// return NO because You have already done it in above code
return NO;
}
The simplest way would be to implement the editing changed method of the text field and set the textfield's text value to upper case representation of the entered text.
#property (nonatomic, strong) IBOutlet UITextField *yourTextfield
// add target in code or use interface builder
[self.yourTextField addTarget:self
action:#selector(uppercaseTextField)
forControlEvents:UIControlEventEditingChanged];
- (IBAction)uppercaseTextField:(UITextField*)textField
{
textField.text = [textField.text uppercaseString];
}
Finally I found the way that respects also editing text in the middle of the string in UITextField.
The problem is that if you replace whole text by UITextFiled.text property the actual cursor moves to end of text. So you need to use .replace() method to specify exactly which characters you want to update to upperCase.
Last thing is to return string.isEmpty as return value of function - otherwise you are not allowing deleting of text.
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if let text = textField.text, let textRange = Range(range, in: text) {
let uppercasedString = string.uppercased()
let updatedText = text.replacingCharacters(in: textRange, with: uppercasedString)
if let selectedTextRange = textField.selectedTextRange {
textField.replace(selectedTextRange, withText: uppercasedString)
approveButtonState(vin: updatedText)
}
return string.isEmpty
}
return false
}
Maybe it's a bit late for an answer here, but as I have a working solution someone might find it useful.
Well, in the following textfield delegate method, check if the new string contains any lowercase characters. If so, then:
Append the character that was just typed to the textfield's text.
Make all the textfield's text uppercased.
Make sure that false is returned by the method.
Otherwise just return true and let the method work as expected.
Here's its implementation:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
var returnValue = true
let lowercaseRange = string.rangeOfCharacter(from: CharacterSet.lowercaseLetters)
if let _ = lowercaseRange?.isEmpty {
returnValue = false
}
if !returnValue {
textField.text = (textField.text! + string).uppercased()
}
return returnValue
}
The above has worked perfectly for me, and a similar implementation works for textviews too, after making the proper adjustments first of course.
Hope it helps!
/**
We take full control of the text entered so that lowercase cannot be inserted
we replace lowercase to uppercase
*/
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
// No spaces allowed
if string == " " {
return false
}
// delete key pressed
if string == "" {
textField.deleteBackward()
return false
}
// We only allow alphabet and numbers
let numbersAndLettersSet = CharacterSet.alphanumerics
if string.lowercased().rangeOfCharacter(from: numbersAndLettersSet) == nil {
return false
}
// Add the entered text
textField.insertText(string.uppercased())
// Return false as we are doing full control
return false
}
Here there's my situation and how I achieved to force the upper text:
custom class (UITextField subclass)
don't want to use delegate UITextFieldDelegate methods
Solution proposed from #CodeBender was pretty much what I was looking for but the cursor always jump to the end as noticed from #Dan.
class MyCustomTextField: UITextField {
...
addTarget(self, action: #selector(upperText), for: .editingChanged)
...
...
#objc private func upperText() {
let textRange = selectedTextRange
text = text?.uppercased()
selectedTextRange = textRange
}
This will set the cursor always in the correct position (where it was) even if user adds text in "the middle".
On text change we can change to uppercase
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if textField == txtEmail {
textField.text = (textField.text! as NSString).replacingCharacters(in: range, with: string.uppercased())
return false
}
return true
}
Using the following text field delegate method it can be done:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)string {
//--- Making uppercase ---//
if (textField == yourTextField ) {
NSRange lowercaseCharRange;
lowercaseCharRange = [string rangeOfCharacterFromSet:[NSCharacterSet lowercaseLetterCharacterSet]];
if (lowercaseCharRange.location != NSNotFound) {
textField.text = [textField.text stringByReplacingCharactersInRange:range
withString:[string uppercaseString]];
return NO;
}
}
}
Hope this helps.

Resources