Related
How can I move control to next text field automatically after entering 10 digit.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSString *currentString = [textField.text stringByReplacingCharactersInRange:range withString:string];
int length = [currentString length];
if (length > 10) {
[yourNextTextfield becomeFirstResponder];
return NO; // add the line
}
return YES;
}
choice no-2
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSUInteger newLength = [textField.text length] + [string length] - range.length;
if (newLength >10)
{
[yournextTextfield becomeFirstResponder];
return NO;
}
return YES;
}
Swift
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
var currentString: String = textField.text!.stringByReplacingCharactersInRange(range, withString: string)
var length: Int = currentString.characters.count
if length > 10 {
yourNextTextfield.becomeFirstResponder()
return false
// add the line
}
return true
}
Another Choice
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
var newLength: Int = textField.text!.characters.count + string.characters.count - range.length
if newLength > 10 {
yournextTextfield.becomeFirstResponder()
return false
}
return true
}
-(BOOL)textFieldShouldReturn:(UITextField*)textField{
NSInteger nextTag = textField.tag + 1;
// Try to find next responder
UIResponder* nextResponder = [textField.superview viewWithTag:nextTag];
if (nextResponder) {
// Found next responder, so set it.
[nextResponder becomeFirstResponder];
} else {
// Not found, so remove keyboard.
[textField resignFirstResponder];
}
return NO; // We do not want UITextField to insert line-breaks.
}
if you have multiple textfield you can also use this
-(BOOL) textFieldShouldReturn:(UITextField*) textField
{
if (textField == txt1){
[txt1 resignFirstResponder];
[txt2 becomeFirstResponder];
}
if (textField == txt2){
[txt2 resignFirstResponder];
}
return YES;
}
Don't forget to add delegate UITextFieldDelegate to your UITextfield
I just want to know how to limit uitextfield range, i.e I have one textbox in that I enter values 10 digit. If I try to type more than 10 digit my textfield should not accept the values. To be very simple I want only 10 digit should be enter in the textfield.
I work out this code but its not worked for me:
- (BOOL)textField:(UITextField *) textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSUInteger oldLength = [textField.text length];
NSUInteger replacementLength = [string length];
NSUInteger rangeLength = range.length;
NSUInteger newLength = oldLength - rangeLength + replacementLength;
BOOL returnKey = [string rangeOfString: #"\n"].location != NSNotFound;
return newLength <= MAXLENGTH || returnKey;
}
To limit a text input's length implement this method of UITextFieldDelegate and check a text's length after changing:
- (BOOL) textField:(UITextField *)textField
shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)string {
NSString *resultText = [textField.text stringByReplacingCharactersInRange:range
withString:string];
return resultText.length <= 10;
}
In Swift 3.0
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let charsLimit = 10
let startingLength = textField.text?.characters.count ?? 0
let lengthToAdd = string.characters.count
let lengthToReplace = range.length
let newLength = startingLength + lengthToAdd - lengthToReplace
return newLength <= charsLimit
}
Try below code that is restricted to 10 digital text.
- (BOOL)textField:(UITextField *) textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSInteger length = [textField.text length];
if (length>9 && ![string isEqualToString:#""]) {
return NO;
}
// This code will provide protection if user copy and paste more then 10 digit text
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
if ([textField.text length]>10) {
textField.text = [textField.text substringToIndex:10];
}
});
return YES;
}
Hope this help you.
Swift 3 Version
func textField(_ textField: UITextField, shouldChangeCharactersIn range:NSRange, replacementString string: String) -> Bool
{
let currentCharacterCount = textField.text?.characters.count ?? 0
if (range.length + range.location > currentCharacterCount){
return false
}
let newLength = currentCharacterCount + string.characters.count - range.length
return newLength <= 10
}
Try this.
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
if(range.length + range.location > textField.text.length)
{
return NO;
}
NSUInteger newLength = [textField.text length] + [string length] - range.length;
return (newLength > 10) ? NO : YES;}
You can use this...i hope it will help you/
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
int lenght1 = code.text.length - range.length + string.length;
if (textField.text.length >= 4 && range.length == 0)
return NO;
I built a really nice subclass of UITextField to limit the number of characters inputted into a field. Here you go!:
public class NumberFormattedTextField : UITextField {
#IBInspectable public var maximumCharacters = 10 {
didSet {
format()
}
}
public override func awakeFromNib() {
format()
addTarget(self, action: "format", forControlEvents: .EditingChanged)
}
func format() {
let len = text.lengthOfBytesUsingEncoding(NSUTF8StringEncoding)
// truncate for max characters if needed
if len > maximumCharacters {
text = text[1...maximumCharacters] // pulls in the last entered character and drops the first one off to preserve length
}
}
}
This depends on a subscript for String. Here's that too:
public extension String {
public subscript (r: Range<Int>) -> String? {
let l = self.lengthOfBytesUsingEncoding(NSUTF8StringEncoding)
if r.startIndex <= l && r.endIndex <= l {
return substringWithRange(Range(start: advance(startIndex, r.startIndex), end: advance(startIndex, r.endIndex)))
} else {
return nil
}
}
}
I have build a subclass based on the answer given by Oxcug without the need for creating an extension in String file and max characters length can be set from storyboard and from swift file as well.:
#IBDesignable class CustomTextField: UITextField {
#IBInspectable var maximumCharacters: Int = 80 {
didSet {
limitCharacters()
}
}
override func awakeFromNib() {
super.awakeFromNib()
limitCharacters()
addTarget(self, action: #selector(CustomTextField.limitCharacters), for: .editingChanged)
}
func limitCharacters() {
guard text != nil else {
return
}
if (text?.characters.count)! > maximumCharacters {
if let range = text?.index(before: (text?.endIndex)!) {
text = text?.substring(to: range)
}
}
}
}
Best Solution:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
return range.location < 10 //Here 10 is your character limit
}
The iPad does not have a "Numpad" keyboard like the iPhone/iPod does.
I'm looking to find how I can restrict the user's keyboard to only accept values 0 through 9.
I would imagine using UITextField's "shouldChangeCharactersInRange" but I don't know the best way to implement it.
This is how you might handle the problem on a SSN verification field, you can modify the max length and remove the if statement checking for keyboard type if you need to.
There is also logic to suppress the max length alerts when the user is typing as opposed to pasting data.
Within the context of this code, presentAlert()/presentAlert: is just some basic function that presents a UIAlertController (or a legacy UIAlertView) using the message string passed.
Swift 5
// NOTE: This code assumes you have set the UITextField(s)'s delegate property to the
// object that will contain this code, because otherwise it would never be called.
//
// There are also some better stylistic approaches in Swift to avoid all the
// nested statements, but I wanted to keep the styles similar to allow others
// to contrast and compare between the two languages a little easier.
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
// Handle backspace/delete
guard !string.isEmpty else {
// Backspace detected, allow text change, no need to process the text any further
return true
}
// Input Validation
// Prevent invalid character input, if keyboard is numberpad
if textField.keyboardType == .numberPad {
// Check for invalid input characters
if CharacterSet(charactersIn: "0123456789").isSuperset(of: CharacterSet(charactersIn: string)) {
// Present alert so the user knows what went wrong
presentAlert("This field accepts only numeric entries.")
// Invalid characters detected, disallow text change
return false
}
}
// Length Processing
// Need to convert the NSRange to a Swift-appropriate type
if let text = textField.text, let range = Range(range, in: text) {
let proposedText = text.replacingCharacters(in: range, with: string)
// Check proposed text length does not exceed max character count
guard proposedText.count <= maxCharacters else {
// Present alert if pasting text
// easy: pasted data has a length greater than 1; who copy/pastes one character?
if string.count > 1 {
// Pasting text, present alert so the user knows what went wrong
presentAlert("Paste failed: Maximum character count exceeded.")
}
// Character count exceeded, disallow text change
return false
}
// Only enable the OK/submit button if they have entered all numbers for the last four
// of their SSN (prevents early submissions/trips to authentication server, etc)
answerButton.isEnabled = (proposedText.count == 4)
}
// Allow text change
return true
}
Objective-C
// NOTE: This code assumes you have set the UITextField(s)'s delegate property to the
// object that will contain this code, because otherwise it would never be called.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
// Handle backspace/delete
if (!string.length)
{
// Backspace detected, allow text change, no need to process the text any further
return YES;
}
// Input Validation
// Prevent invalid character input, if keyboard is numberpad
if (textField.keyboardType == UIKeyboardTypeNumberPad)
{
if ([string rangeOfCharacterFromSet:[NSCharacterSet decimalDigitCharacterSet].invertedSet].location != NSNotFound)
{
[self presentAlert: #"This field accepts only numeric entries."];
return NO;
}
}
// Length Validation
NSString *proposedText = [textField.text stringByReplacingCharactersInRange:range withString:string];
// Check proposed text length does not exceed max character count
if (proposedText.length > maxCharacters)
{
// Present alert if pasting text
// easy: pasted data has a length greater than 1; who copy/pastes one character?
if (string.length > 1)
{
// Pasting text, present alert so the user knows what went wrong
[self presentAlert: #"Paste failed: Maximum character count exceeded."];
}
// Character count exceeded, disallow text change
return NO;
}
// Only enable the OK/submit button if they have entered all numbers for the last four
// of their SSN (prevents early submissions/trips to authentication server, etc)
self.answerButton.enabled = (proposedText.length == maxCharacters);
// Allow text change
return YES;
}
You can use this code to allow only number in textField.
Before that set delegate for textField
textFieldName.delegate=self;
or
[textFieldName setDelegate:self];
Than use this code to allow only digit to textField
- (BOOL) textField: (UITextField *)theTextField shouldChangeCharactersInRange:(NSRange)range replacementString: (NSString *)string {
//return yes or no after comparing the characters
// allow backspace
if (!string.length)
{
return YES;
}
////for Decimal value start//////This code use use for allowing single decimal value
// if ([theTextField.text rangeOfString:#"."].location == NSNotFound)
// {
// if ([string isEqualToString:#"."]) {
// return YES;
// }
// }
// else
// {
// if ([[theTextField.text substringFromIndex:[theTextField.text rangeOfString:#"."].location] length]>2) // this allow 2 digit after decimal
// {
// return NO;
// }
// }
////for Decimal value End//////This code use use for allowing single decimal value
// allow digit 0 to 9
if ([string intValue])
{
return YES;
}
return NO;
}
Try this to avoid textfield clearing issue
Swift 3.0
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
guard NSCharacterSet(charactersInString: "0123456789").isSupersetOfSet(NSCharacterSet(charactersInString: string)) else {
return false
}
return true
}
Swift 4.0
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
guard CharacterSet(charactersIn: "0123456789").isSuperset(of: CharacterSet(charactersIn: string)) else {
return false
}
return true
}
Very specific steps for Swift code
You can provide logic that restricts the text field's input in the func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool method by implementing the UITextFieldDelegate protocol.
For the sake of clarity, these steps assume that your storyboard contains a View Controller with a text field object that should only accept digits.
Create a custom class for the view controller that extends UIViewController. Make sure that the scene in your storyboard refers to the custom class by setting the custom class value in Xcode's Identity Inspector.
import UIKit
class YourCustomController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
}
Create an outlet from your scene's text field to your custom View Controller.
class YourCustomController: UIViewController {
#IBOutlet weak var numberField: UITextField!
...
}
Apply the UITextFieldDelegate protocol in your custom view controller.
class YourCustomController: UIViewController, UITextFieldDelegate {
...
}
In your custom view controller's viewDidLoad method, assign your text field's delegate to your custom view controller class.
override func viewDidLoad() {
super.viewDidLoad()
numberField.delegate = self
}
Add the UITextFieldDelegate's func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool method.
As a result of making your custom view controller the numberField's delegate in the previous step, this method will be called each time a user enters a character into the text field. If your method returns true then the character will remain in the text field. If your method returns false then the character will not remain in the text field.
The string parameter is the character being entered by the user. If the string character can be converted to an Int then it is between 0 and 9; otherwise, it is some non-number character.
class YourCustomController: UIViewController, UITextFieldDelegate {
...
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
return Int(string) != nil
}
}
(See below for the full view controller code.)
Example View Controller with digits only text field
import UIKit
class YourCustomController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var numberField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
numberField.delegate = self
}
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
return Int(string) != nil
}
}
Example View Controller with a Decimal text field
If you want to support a decimal number then take advantage of NSNumberFormatter. See the code comments for the differences.
import UIKit
class YourCustomController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var numberField: UITextField!
private var formatter: NSNumberFormatter!
override func viewDidLoad() {
super.viewDidLoad()
numberField.delegate = self
// Initialize the formatter; minimum value is set to zero; style is Decimal.
formatter = NSNumberFormatter()
formatter.numberStyle = NSNumberFormatterStyle.DecimalStyle
formatter.minimum = 0
}
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
// Combine the current text field value and the new string
// character. If it conforms to the formatter's settings then
// it is valid. If it doesn't then nil is returned and the
// string character should not be allowed in the text field.
return formatter.numberFromString("\(textField.text)\(string)") != nil
}
}
- (BOOL) textField: (UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString: (NSString *)string {
NSNumberFormatter * nf = [[NSNumberFormatter alloc] init];
[nf setNumberStyle:NSNumberFormatterNoStyle];
NSString * newString = [NSString stringWithFormat:#"%#%#",textField.text,string];
NSNumber * number = [nf numberFromString:newString];
if (number)
return YES;
else
return NO;
}
I applied this and it works!!
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
// Check for non-numeric characters
NSUInteger lengthOfString = string.length;
for (NSInteger index = 0; index < lengthOfString; index++) {
unichar character = [string characterAtIndex:index];
if (character < 48) return NO; // 48 unichar for 0
if (character > 57) return NO; // 57 unichar for 9
}
// Check total length for restrict user
NSUInteger proposedNewLength = textField.text.length - range.length + string.length;
if (proposedNewLength > 6)
return YES;
return YES;
}
swift 5
//MARK:- UITextFieldDelegate
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let allowedCharacters = "1234567890"
let allowedCharcterSet = CharacterSet(charactersIn: allowedCharacters)
let typedCharcterSet = CharacterSet(charactersIn: string)
return allowedCharcterSet.isSuperset(of: typedCharcterSet)
}
You can now just tap 1234567890 only
NSString* val = [[textField text] stringByReplacingCharactersInRange:range withString:string];
NSCharacterSet *allowedCharacterSet = [NSCharacterSet decimalDigitCharacterSet];
if ([[string componentsSeparatedByCharactersInSet:[allowedCharacterSet invertedSet]] count] > 1 || [val length] > 5) {
return NO;
}
Works fine for me :
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
if (([string rangeOfCharacterFromSet:[[NSCharacterSet decimalDigitCharacterSet] invertedSet]].location != NSNotFound) && !(range.length==1 && string.length==0)) {
return NO;
}
return YES;
}
In Swift:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
return string.isEmpty || Int(string) != nil
}
Keep distinct presentation data from internal representation. There is a simpler way. Let NSNumberFormatter do the job:
NSNumberFormatter* ns = [[NSNumberFormatter alloc] init];
ns.numberStyle = NSNumberFormatterDecimalStyle;
[ns setMaximumFractionDigits:2];
// This is your internal representation of the localized number
double a = [[ns numberFromString:self.textIVA.text] doubleValue]];
[mylabel setText:[NSString stringWithFormat:#"€ %#",
[NSNumberFormatter localizedStringFromNumber:
[NSNumber numberWithDouble:a]
numberStyle:NSNumberFormatterDecimalStyle]]];
If you use my specification pattern then code looks like this
textField.delegate = self
lazy var specification: Specification = {
return RegularExpressionSpecification(pattern: "^(|0|[1-9]\\d{0,6})$")
}()
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
let textFieldString: NSString = textField.text ?? ""
let s = textFieldString.stringByReplacingCharactersInRange(range, withString:string)
return specification.isSatisfiedBy(s)
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
let s = textField.text ?? ""
let isTextValid = specification.isSatisfiedBy(s)
if isTextValid {
textField.resignFirstResponder()
}
return false
}
I have modified #iDev's answer to work for digitals and ".":
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
// Check for non-numeric characters
NSUInteger lengthOfString = string.length;
for (NSInteger index = 0; index < lengthOfString; index++) {
unichar character = [string characterAtIndex:index];
if ((character < 48) && (character != 46)) return NO;
// 48 unichar for 0, and 46 unichar for point
if (character > 57) return NO;
// 57 unichar for 9
}
// Check for total length
NSUInteger proposedNewLength = textField.text.length - range.length + string.length;
if (proposedNewLength > 6)
return YES;
return YES;
}
swift 3
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if textField==yourTextFieldOutlet {
if(CharacterSet.decimalDigits.isSuperset(of: CharacterSet(charactersIn: yourTextFieldOutlet.text!))){
//if numbers only, then your code here
}
else{
showAlert(title: "Error",message: "Enter Number only",type: "failure")
}
}
return true
}
Use this code:
NSString* val = [[textField text] stringByReplacingCharactersInRange:range withString:string];
NSCharacterSet *allowedCharacterSet = [NSCharacterSet decimalDigitCharacterSet];
if ([[string componentsSeparatedByCharactersInSet:[allowedCharacterSet invertedSet]] count] > 1 || [val length] > 5) {
return NO;
}
I have UITexfields i want that it should accept only number other shows alert that enter a numeric value.
I want that motionSicknessTextFiled should only accept number
NSString*dogswithMotionSickness=motionSicknessTextField.text;
NSString*valueOne=cereniaTextField.text;
NSString*valueTwo=prescriptionTextField.text;
NSString*valueThree=otherMeansTextField.text;
NSString*valueFour=overtheCounterTextField.text;
In whatever UITextField you're getting these values from, you can specify the kind of keyboard you want to appear when somebody touches inside the text field.
E.G. a numeric-only keyboard.
Like this screenshot:
This is easily set when working with the XIB and the Interface Builder built into Xcode, but if you want to understand this programmatically, take a look at Apple's UITextInputTraits protocol reference page, specifically the keyboardType property information.
To filter out punctuations, set the textfield's delegate and set up the shouldChangeCharactersInRange method:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSCharacterSet *numbersOnly = [NSCharacterSet characterSetWithCharactersInString:#"0123456789"];
NSCharacterSet *characterSetFromTextField = [NSCharacterSet characterSetWithCharactersInString:textField.text];
BOOL stringIsValid = [numbersOnly isSupersetOfSet:characterSetFromTextField];
return stringIsValid;
}
Objective C
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if (!string.length)
return YES;
if (textField == self.tmpTextField)
{
NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
NSString *expression = #"^([0-9]+)?(\\.([0-9]{1,2})?)?$";
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:expression
options:NSRegularExpressionCaseInsensitive
error:nil];
NSUInteger numberOfMatches = [regex numberOfMatchesInString:newString
options:0
range:NSMakeRange(0, [newString length])];
if (numberOfMatches == 0)
return NO;
}
return YES;
}
Swift 3.0
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if !string.characters.count {
return true
}
do {
if textField == self.tmpTextField {
var newString = textField.text.replacingCharacters(inRange: range, with: string)
var expression = "^([0-9]+)?(\\.([0-9]{1,2})?)?$"
var regex = try NSRegularExpression(pattern: expression, options: NSRegularExpressionCaseInsensitive)
var numberOfMatches = regex.numberOfMatches(inString: newString, options: [], range: NSRange(location: 0, length: newString.characters.count))
if numberOfMatches == 0 {
return false
}
}
}
catch let error {
}
return true
}
[textField setKeyboardType:UIKeyboardTypeNumberPad];
I've implemented the snippet which has the features for textField:
Check the maximum allowed characters.
Check the valid decimal number.
Check only numeric numbers.
The code is the UITextField delegate method. Before you use this snippet, you must have these properties:
self.maxCharacters
self.numeric // Only int characters.
self.decimalNumeric // Only numbers and ".", "," (for specific locales, like Russian).
Code:
- (BOOL)textField:(UITextField *) textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if(self.numeric || self.decimalNumeric)
{
NSString *fulltext = [textField.text stringByAppendingString:string];
NSString *charactersSetString = #"0123456789";
// For decimal keyboard, allow "dot" and "comma" characters.
if(self.decimalNumeric) {
charactersSetString = [charactersSetString stringByAppendingString:#".,"];
}
NSCharacterSet *numbersOnly = [NSCharacterSet characterSetWithCharactersInString:charactersSetString];
NSCharacterSet *characterSetFromTextField = [NSCharacterSet characterSetWithCharactersInString:fulltext];
// If typed character is out of Set, ignore it.
BOOL stringIsValid = [numbersOnly isSupersetOfSet:characterSetFromTextField];
if(!stringIsValid) {
return NO;
}
if(self.decimalNumeric)
{
NSString *currentText = [textField.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
// Change the "," (appears in other locale keyboards, such as russian) key ot "."
currentText = [currentText stringByReplacingOccurrencesOfString:#"," withString:#"."];
// Check the statements of decimal value.
if([fulltext isEqualToString:#"."]) {
textField.text = #"0.";
return NO;
}
if([fulltext rangeOfString:#".."].location != NSNotFound) {
textField.text = [fulltext stringByReplacingOccurrencesOfString:#".." withString:#"."];
return NO;
}
// If second dot is typed, ignore it.
NSArray *dots = [fulltext componentsSeparatedByString:#"."];
if(dots.count > 2) {
textField.text = currentText;
return NO;
}
// If first character is zero and second character is > 0, replace first with second. 05 => 5;
if(fulltext.length == 2) {
if([[fulltext substringToIndex:1] isEqualToString:#"0"] && ![fulltext isEqualToString:#"0."]) {
textField.text = [fulltext substringWithRange:NSMakeRange(1, 1)];
return NO;
}
}
}
}
// Check the max characters typed.
NSUInteger oldLength = [textField.text length];
NSUInteger replacementLength = [string length];
NSUInteger rangeLength = range.length;
NSUInteger newLength = oldLength - rangeLength + replacementLength;
BOOL returnKey = [string rangeOfString: #"\n"].location != NSNotFound;
return newLength <= _maxCharacters || returnKey;
}
Demo:
Modified Michael Dautermann's answer:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if(string.length > 0)
{
NSCharacterSet *numbersOnly = [NSCharacterSet characterSetWithCharactersInString:#"0123456789"];
NSCharacterSet *characterSetFromTextField = [NSCharacterSet characterSetWithCharactersInString:string];
BOOL stringIsValid = [numbersOnly isSupersetOfSet:characterSetFromTextField];
return stringIsValid;
}
return YES;
}
swift 4
This allows only number input and you can also set character limitation
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let aSet = NSCharacterSet(charactersIn:"0123456789").inverted
let compSepByCharInSet = string.components(separatedBy: aSet)
let numberFiltered = compSepByCharInSet.joined(separator: "")
if string == numberFiltered {
let currentText = textField.text ?? ""
guard let stringRange = Range(range, in: currentText) else { return false }
let updatedText = currentText.replacingCharacters(in: stringRange, with: string)
return updatedText.count <= 10
} else {
return false
}
}
Here is Swift solution:
In viewDidLoad set the delegate:
_yourTextField.delegate = self
let _acceptableCharacters = "0123456789."
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
if (string.characters.count == 0) {
return true
}
if (textField == self._yourTextField) {
let cs = NSCharacterSet(charactersInString: self._acceptableCharacters)
let filtered = string.componentsSeparatedByCharactersInSet(cs).filter { !$0.isEmpty }
let str = filtered.joinWithSeparator("")
return (string != str)
}
return true
}
this is the function which checks for the String contains Numeric value only
+(BOOL) checkforNumeric:(NSString*) str
{
NSString *strMatchstring=#"\\b([0-9%_.+\\-]+)\\b";
NSPredicate *textpredicate=[NSPredicate predicateWithFormat:#"SELF MATCHES %#", strMatchstring];
if(![textpredicate evaluateWithObject:str])
{
//////NSLog(#"Invalid email address found");
UIAlertView *objAlert = [[UIAlertView alloc] initWithTitle:APP_NAME message:#"please enter valid text." delegate:nil cancelButtonTitle:nil otherButtonTitles:#"Close",nil];
[objAlert show];
[objAlert release];
return FALSE;
}
return TRUE;
}
check it on submit button.
This answer threw some error in Swift 3, here's the working answer:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if string.characters.count == 0 {
return true
}
do {
if textField == self.numberTextField {
let nString = textField.text as NSString?
let newString = nString?.replacingCharacters(in: range, with: string)
let expression = "^([0-9]+)?(\\.([0-9]{1,2})?)?$"
let regex = try NSRegularExpression(pattern: expression, options: .caseInsensitive)
let numberOfMatches = regex.numberOfMatches(in: newString! as String, options: [], range: NSRange(location: 0, length: (newString?.characters.count)!))
if numberOfMatches == 0 {
return false
}
}
}
catch let error {
}
return true
}
I just modified the answer of Michael and made it a little bit easier to implement. Just make sure that the delegate of your UITextfield is set to itself.
yourTxtField.delegate = self;
Furthermore copy & paste this code into your main file.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
if (textField == yourTxtField) {
NSCharacterSet *numbersOnly = [NSCharacterSet characterSetWithCharactersInString:#"0123456789"];
NSCharacterSet *characterSetFromTextField = [NSCharacterSet characterSetWithCharactersInString:string];
BOOL stringIsValid = [numbersOnly isSupersetOfSet:characterSetFromTextField];
return stringIsValid;
}else {
return YES;
}
}
If you want to allow the use of the spacebar just put in a blank space at the end of the CharactersInString, just like so:
#"0123456789" -> #"0123456789 "
Additionally:
If you want to restrict the length of the string just replace the if-function with following:
if (textField == yourTxtField) {
NSUInteger newLength = [textField.text length] + [string length] - range.length;
NSCharacterSet *cs = [[NSCharacterSet characterSetWithCharactersInString:#"1234567890"] invertedSet];
NSString *filtered = [[string componentsSeparatedByCharactersInSet:cs] componentsJoinedByString:#""];
return (([string isEqualToString:filtered])&&(newLength <= 10));
}
In my case the "10" at the end represents the limit of characters.
Cheers! :)
Swift 4.2 port of the best answer here by #almas-adlibek
A bunch of configuration variables:
private let kMaxTextLength = 8
private let kZeroDotted = "0."
private let kZero = "0"
private let kDoubleDot = ".."
private let kDot = "."
private let kPeriod = ","
Now the Swift 4 converted part of the code.
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
guard let oldText = textField.text, let swiftRange = Range(range, in: oldText) else {
return true
}
let newText = oldText.replacingCharacters(in: swiftRange, with: string)
var currentText = textField.text?.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
// Change the "," (appears in other locale keyboards, such as russian) key ot "."
currentText = currentText?.replacingOccurrences(of: kPeriod, with: kDot)
// Check the statements of decimal value.
if (newText == kDot) {
textField.text = kZeroDotted;
return false
}
if (newText.range(of: kDoubleDot) != nil) {
textField.text = newText.replacingOccurrences(of: kDoubleDot, with: kDot);
return false
}
// If second dot is typed, ignore it.
let dots = newText.components(separatedBy: kDot)
if(dots.count > 2) {
textField.text = currentText;
return false
}
// If first character is zero and second character is > 0, replace first with second. 05 => 5;
if(newText.count == 2) {
if(newText[0...0] == kZero && newText != kZeroDotted) {
textField.text = newText[1...1]
return false
}
}
// Check the max characters typed.
let oldLength = textField.text?.count ?? 0
let replacementLength = string.count
let rangeLength = range.length
let newLength = oldLength - rangeLength + replacementLength;
let returnKey = string.rangeOfCharacter(from: CharacterSet.newlines) != nil
return newLength <= kMaxTextLength || returnKey;
}
Swift
class ExampleVC: UIViewController {
let numbers = "0123456789";
override func viewDidLoad() {
super.viewDidLoad()
let textfield = UITextField(frame: CGRectMake(20, 100, 300, 44))
//make some customization, if you want
self.view.addSubview(textfield)
textfield.delegate = self;
}
}
extension ExampleVC: UITextFieldDelegate {
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
return string.characters.count > 0 ? numbers.contains(string) : true
}
}
Another option of entering only numeric values into your text field is by selecting the keyboard type attribute of the corresponding textfield. Attaching the screenshot for reference.
Here is the working example for swift 4
public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool
{
// Allow Backspace
if string.count == 0 {
return true
}
// Allow Only Valid Decimal Numbers
if let textFieldText = textField.text {
let finalText = (textFieldText as NSString).replacingCharacters(in: range, with: string)
if Double(finalText) != nil {
return true
}
}
return false
}
I have a UITextField that when clicked brings up a number pad with a decimal point in the bottom left. I am trying to limit the field so that a user can only place 1 decimal mark
e.g.
2.5 OK
2..5 NOT OK
Implement the shouldChangeCharactersInRange method like this:
// Only allow one decimal point
// Example assumes ARC - Implement proper memory management if not using.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
NSArray *arrayOfString = [newString componentsSeparatedByString:#"."];
if ([arrayOfString count] > 2 )
return NO;
return YES;
}
This creates an array of strings split by the decimal point, so if there is more than one decimal point we will have at least 3 elements in the array.
Here is an example with a regular expression, the example limits to only one decimal point and 2 decimals. You can tweak it to fit your needs.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
NSString *expression = #"^[0-9]*((\\.|,)[0-9]{0,2})?$";
NSError *error = nil;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:expression options:NSRegularExpressionCaseInsensitive error:&error];
NSUInteger numberOfMatches = [regex numberOfMatchesInString:newString options:0 range:NSMakeRange(0, [newString length])];
return numberOfMatches != 0;
}
Swift 3 Implement this UITextFieldDelegate method to prevent user from typing an invalid number:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let text = (textField.text ?? "") as NSString
let newText = text.replacingCharacters(in: range, with: string)
if let regex = try? NSRegularExpression(pattern: "^[0-9]*((\\.|,)[0-9]*)?$", options: .caseInsensitive) {
return regex.numberOfMatches(in: newText, options: .reportProgress, range: NSRange(location: 0, length: (newText as NSString).length)) > 0
}
return false
}
It is working with both comma or dot as decimal separator. You can also limit number of fraction digits using this pattern: "^[0-9]*((\\.|,)[0-9]{0,2})?$" (in this case 2).
Swift 4
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
// Allow to remove character (Backspace)
if string == "" {
return true
}
// Block multiple dot
if (textField.text?.contains("."))! && string == "." {
return false
}
// Check here decimal places
if (textField.text?.contains("."))! {
let limitDecimalPlace = 2
let decimalPlace = textField.text?.components(separatedBy: ".").last
if (decimalPlace?.count)! < limitDecimalPlace {
return true
}
else {
return false
}
}
return true
}
Objective-C
//Create this variable in .h file or .m file
float _numberOfDecimal;
//assign value in viewDidLoad method
numberOfDecimal = 2;
#pragma mark - TextFieldDelegate
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
// Allow to remove character (Backspace)
if ([string isEqualToString:#""]) {
return true;
}
// Block multiple dot
if ([textField.text containsString:#"."] && [string isEqualToString:#"."]) {
return false;
}
// Check here decimal places
if ([textField.text containsString:#"."]) {
NSString *strDecimalPlace = [[textField.text componentsSeparatedByString:#"."] lastObject];
if (strDecimalPlace.length < _numberOfDecimal) {
return true;
}
else {
return false;
}
}
return true;
}
For Swift 2.3 to prevent user for enter decimal number after two places -
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool
{
let decimalPlacesLimit = 2
let rangeDot = txtPrice.text!.rangeOfString(".", options: .CaseInsensitiveSearch)
if rangeDot?.count > 0
{
if (string == ".")
{
print("textField already contains a separator")
return false
}
else {
var explodedString = txtPrice.text!.componentsSeparatedByString(".")
let decimalPart = explodedString[1]
if decimalPart.characters.count >= decimalPlacesLimit && !(string == "")
{
print("textField already contains \(decimalPlacesLimit) decimal places")
return false
}
}
}
}
Building on the accepted answer, the following approach validates three cases that are helpful when dealing with money formats:
Extremely large amounts
More than 2 characters after the decimal point
More than 1 decimal points
Make sure your text field's delegate is set properly, your class conforms to the UITextField protocol, and add the following delegate method.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
// Check for deletion of the $ sign
if (range.location == 0 && [textField.text hasPrefix:#"$"])
return NO;
NSString *updatedText = [textField.text stringByReplacingCharactersInRange:range withString:string];
NSArray *stringsArray = [updatedText componentsSeparatedByString:#"."];
// Check for an absurdly large amount
if (stringsArray.count > 0)
{
NSString *dollarAmount = stringsArray[0];
if (dollarAmount.length > 6)
return NO;
}
// Check for more than 2 chars after the decimal point
if (stringsArray.count > 1)
{
NSString *centAmount = stringsArray[1];
if (centAmount.length > 2)
return NO;
}
// Check for a second decimal point
if (stringsArray.count > 2)
return NO;
return YES;
}
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if(textField == min_textfield )
{
if([textField.text rangeOfString:#"."].location == NSNotFound)
{
if([string isEqualToString:#"."] )
{
flag_for_text = 1;
}
else
{
textField.text = [NSMutableString stringWithFormat:#"%#",textField.text];
}
}
else
{
if([string isEqualToString:#"."])
{
return NO;
}
else
{
textField.text = [NSMutableString stringWithFormat:#"%#",textField.text];
}
}
}
}
Try this :-
public func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {
if(text == "," || text == "." ){
let countdots = textView.text!.componentsSeparatedByString(".").count - 1
if countdots > 0 && (text == "." || text == "," )
{
return false
}
}
return true
}
Swift 3
No need to create an array and check count. Limit user can only place 1 decimal mark like this.
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if (textField.text?.contains("."))! && string.contains(".")
{
return false
}
else
{
return true
}
}
Swift 4
max number of Integers Numbers is 4 i.e., 9999, and max decimal digits limit is 2. So, max number can be 9999.99
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
// 100 is the tag value of our textfield
/*or you may use "if textfield == myTextField{" if you have an IBOutlet to that textfield */
if textField.tag == 100 {
//max length limit of text is 8
if textField.text!.count > 8 && string != "" {
return false
}
let maxLength = 8
let currentString: NSString = textField.text! as NSString
// Use following code If you are inputting price to that text field and want $ to get inserted automatically at start when user starts typing in that textfield or you may put some other character at start instead of $. Otherwise comment the following 3 lines of if condition code
if currentString.length == 0 {
priceTextField.text = "$"
}
//new string after inserting the new entered characters
let newString: NSString =
currentString.replacingCharacters(in: range, with: string) as NSString
if newString.length > maxLength{
return false
}
if (textField.text!.range(of: ".") != nil) {
let numStr = newString.components(separatedBy: ".")
if numStr.count>1{
let decStr = numStr[1]
if decStr.length > 2{
return false
}
}
}
var priceStr: String = newString as String
if (textField.text!.range(of: "$") != nil) {
priceStr = priceStr.replacingOccurrences(of: "$", with: "")
}
let price: Double = Double(priceStr) ?? 0
if price > 9999.99{
return false
}
switch string {
case "0","1","2","3","4","5","6","7","8","9":
return true
case ".":
let array = Array(textField.text!)
var decimalCount = 0
for character in array {
if character == "." {
decimalCount = decimalCount + 1
}
}
if decimalCount == 1 {
return false
} else {
return true
}
default:
let array = Array(string)
if array.count == 0 {
return true
}
return false
}
}
return true
}
SWIFT 5
Improvement
Info : do not allow :
separator at the beginning
zero plus another digit at the start except when you add a separator after
1: set the keyboard type to : Decimal Pad
2: copy past
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
//!\ set the keyboard type to : Decimal Pad /!\\
// CUSTOM SETUP
let c = NSLocale.current.decimalSeparator ?? "."
let limitBeforeSeparator = 2
let limitAfterSeparator = 2
// ---------
var validatorUserInput:Bool = false
let text = (textField.text ?? "") as NSString
let newText = text.replacingCharacters(in: range, with: string)
// Validator
let pattern = "(?!0[0-9])\\d*(?!\\\(c))^[0-9]{0,\(limitBeforeSeparator)}((\\\(c))[0-9]{0,\(limitAfterSeparator)})?$"
if let regex = try? NSRegularExpression(pattern: pattern, options: .caseInsensitive) {
validatorUserInput = regex.numberOfMatches(in: newText, options: .reportProgress, range: NSRange(location: 0, length: (newText as NSString).length)) > 0
}
if validatorUserInput {
// setting data or something eles before the return
if let char = string.cString(using: String.Encoding.utf8) {
let isBackSpace = strcmp(char, "\\b")
if (isBackSpace == -92 && textField.text?.count == 1) {
print("Backspace was pressed")
print(newText)
// do something...
} else {
print("Number Added")
print(newText)
// do something...
}
}
return validatorUserInput
} else {
return validatorUserInput
}
}
3: set in the method, if you want x maximum number of digits before and after the separator
let limitBeforeSeparator = 2
let limitAfterSeparator = 2
In whatever object you set your UITextField's delegate to, add a method that answers to "[- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string]".
Then you can either use a NSNumberFormatter object or you can brute force check for an already existing decimal place mark (returning NO if a decimal mark already exists).
Short told, the number format is as follows [NSString stringWithFormat:#"%9.5f", x]; Where 5 is the decimal after ",".
I made the solution, that brings you control over decimal places count, so user can type only one decimal separator and you can also have a control over decimal places count.
Just set the decimalPlacesLimit value properly.
See the method:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSLog(#"text on the way: %#", string);
NSUInteger decimalPlacesLimit = 2;
NSRange rangeDot = [textField.text rangeOfString:#"." options:NSCaseInsensitiveSearch];
NSRange rangeComma = [textField.text rangeOfString:#"," options:NSCaseInsensitiveSearch];
if (rangeDot.length > 0 || rangeComma.length > 0){
if([string isEqualToString:#"."]) {
NSLog(#"textField already contains a separator");
return NO;
} else {
NSArray *explodedString = [textField.text componentsSeparatedByString:#"."];
NSString *decimalPart = explodedString[1];
if (decimalPart.length >= decimalPlacesLimit && ![string isEqualToString:#""]) {
NSLog(#"textField already contains %d decimal places", decimalPlacesLimit);
return NO;
}
}
}
return YES;
}
Swift 4
The efficient and easy way to avoid multiple decimal points (. or ,) in UITextField:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if(string == "," || string == "." ){
if ((textField.text?.contains(","))! || (textField.text?.contains("."))!){
return false
}
}
return true
}
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
if([string isEqualToString:#"."]) {
BOOL containsDecimal = [textField.text containsString:#"."];
return !containsDecimal;
}
return YES;
}
If textfield text already contains a '.' then return NO else return YES.
Thanks everyone, I needed to limit the number before and after the dot. It was only with a regular expression that this became possible for me.
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if string == "," {
textField.text = textField.text! + "."
return false
}
guard let newTextField = textField.text else { return false }
if !string.isEmpty {
let text = newTextField as NSString
let newText = text.replacingCharacters(in: range, with: string)
if let regex = try? NSRegularExpression(pattern: "^[0-9]{0,4}$*((\\.|,)[0-9]{0,4})?$", options: .caseInsensitive) {
return regex.numberOfMatches(in: newText, options: .reportProgress, range: NSRange(location: 0, length: (newText as NSString).length)) > 0
}
return false
}
return true
// #"^[0-9]{0,3}$*((\\.|,)[0-9]{0,2})?$"
}