Cómo restringir UITextField para tomar solo números en Swift?

Quiero que el usuario solo ingrese valores numéricos en un UITextField . En el iPhone, podemos mostrar el teclado numérico, pero en el iPad el usuario puede cambiar a cualquier teclado.

¿Hay alguna forma de restringir al usuario para ingresar solo valores numéricos en un UITextField ?

Aquí están mis 2 centavos. (Probado solo en Swift 2)

 func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { let aSet = NSCharacterSet(charactersInString:"0123456789").invertedSet let compSepByCharInSet = string.componentsSeparatedByCharactersInSet(aSet) let numberFiltered = compSepByCharInSet.joinWithSeparator("") return string == numberFiltered } 

Esto es solo un poco más estricto. Sin punto decimal tampoco.

Espero eso ayude 🙂

PD: Supuse que cuidabas al delegado de todos modos.

Actualización: Swift 3.0 :

 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: "") return string == numberFiltered } 

Solución para swift 3.0 y superior

 func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { let allowedCharacters = CharacterSet.decimalDigits let characterSet = CharacterSet(charactersIn: string) return allowedCharacters.isSuperset(of: characterSet) } 

Swift 2.0

Por solo permitir números y un “.” decimal en uitextfield.

 func textField(textField: UITextField,shouldChangeCharactersInRange range: NSRange,replacementString string: String) -> Bool { let newCharacters = NSCharacterSet(charactersInString: string) let boolIsNumber = NSCharacterSet.decimalDigitCharacterSet().isSupersetOfSet(newCharacters) if boolIsNumber == true { return true } else { if string == "." { let countdots = textField.text!.componentsSeparatedByString(".").count - 1 if countdots == 0 { return true } else { if countdots > 0 && string == "." { return false } else { return true } } } else { return false } } } 

Acepte valores decimales en campos de texto con un solo punto (.) En Swift 3

 func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { let inverseSet = NSCharacterSet(charactersIn:"0123456789").inverted let components = string.components(separatedBy: inverseSet) let filtered = components.joined(separator: "") if filtered == string { return true } else { if string == "." { let countdots = textField.text!.components(separatedBy:".").count - 1 if countdots == 0 { return true }else{ if countdots > 0 && string == "." { return false } else { return true } } }else{ return false } } } 
 func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { // return true if the replacementString only contains numeric characters let digits = NSCharacterSet.decimalDigitCharacterSet() for c in string { if !digits.characterIsMember(c) { return false } } return true } 

Esta solución funcionará incluso si el usuario cambia teclados o intenta pegar una cadena no numérica en el campo de texto.

Asegúrese de establecer la propiedad de delegate del campo de texto apropiado.

En cualquier UITextField al que obtenga estos valores, puede especificar el tipo de teclado que desea que aparezca cuando alguien toca dentro del campo de texto.

EG un teclado numérico solamente.

Como esta captura de pantalla:

enter image description here

En veloz 4.1 y Xcode 9.4.1

Agrega UITextFieldDelegate a tu clase

 class YourViewController: UIViewController, UITextFieldDelegate 

Luego escribe este código en tu viewDidLoad ()

 mobileNoTF.delegate = self 

Escribir esta función de delegado de campo de texto

 //MARK - UITextField Delegates func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { //For mobile numer validation if textField == mobileNoTF { let allowedCharacters = CharacterSet(charactersIn:"+0123456789 ")//Here change this characters based on your requirement let characterSet = CharacterSet(charactersIn: string) return allowedCharacters.isSuperset(of: characterSet) } return true } 

De hecho, lo había hecho al trabajar en el libro de Big Nerd Ranch, mi solución es:

 func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { let newCharacters = NSCharacterSet(charactersInString: string) return NSCharacterSet.decimalDigitCharacterSet().isSupersetOfSet(newCharacters) } 

esto solo permite los números 0-9, para permitir el “.” también es más complicado ya que solo puedes permitir uno “.”

Si bien la mayoría de estas soluciones funcionarán, tenga en cuenta que en algunas localizaciones los decimales se separan con un “,” y no un “.”

La manera más limpia de hacer esto sería

 func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { let decimalCharacter = NSNumberFormatter().decimalSeparator let characterSet = NSMutableCharacterSet.decimalDigitCharacterSet() characterSet.addCharactersInString(decimalCharacter) return replacementString.rangeOfCharacterFromSet(characterSet.invertedSet) == nil } 
 func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { if let numRange = string.rangeOfCharacterFromSet(NSCharacterSet.letterCharacterSet()) { return false } else { return true } } 

Probado en veloz 3.0

 func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { let numberOnly = NSCharacterSet.init(charactersIn: "0123456789") let stringFromTextField = NSCharacterSet.init(charactersIn: string) let strValid = numberOnly.isSuperset(of: stringFromTextField as CharacterSet) return strValid } 

Usar formateador numérico

Swift 4.x

 func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { let s = NSString(string: textField.text ?? "").replacingCharacters(in: range, with: string) guard !s.isEmpty else { return true } let numberFormatter = NumberFormatter() numberFormatter.numberStyle = .none return numberFormatter.number(from: s)?.intValue != nil } 

Creo que puede forzar el cambio del tipo de teclado implementando el protocolo UITextInputTraits, opcional var keyboardType

 //class ViewController: UIViewController, UITextInputTraits { @IBOutlet weak var textFieldKeyboardType: UITextField!{ didSet{ textFieldKeyboardType.keyboardType = UIKeyboardType.NumberPad } } var keyboardType: UIKeyboardType { get{ return textFieldKeyboardType.keyboardType } set{ if newValue != UIKeyboardType.NumberPad{ self.keyboardType = UIKeyboardType.NumberPad } } } 

Como si no hubiera suficientes respuestas, aquí está el mío. Creo que todos los ejemplos permitidos para los separadores decimales tienen fallas en la localización, en los espacios posteriores o en la función copiar / pegar.

 func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { if string.isEmpty {return true} //allow for backspace let decimalSeparator = NSNumberFormatter().decimalSeparator ?? "." let validChars = NSMutableCharacterSet(charactersInString: decimalSeparator) validChars.formUnionWithCharacterSet(NSCharacterSet.decimalDigitCharacterSet()) if validChars.isSupersetOfSet(NSCharacterSet(charactersInString: string)){ switch string.componentsSeparatedByString(decimalSeparator).count-1 { case 0: //no decimals return true case 1: //if adding decimal, only allow if no existing decimal if let existingText = textField.text{ return existingText.componentsSeparatedByString(decimalSeparator).count <= 1 } else {return true} default: //invalid decimals return false } } return false } 

Para permitir solo números y solo un operador decimal, puede usar esta solución:

 func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { let isNumber = NSCharacterSet.decimalDigitCharacterSet().isSupersetOfSet(NSCharacterSet(charactersInString: string)) return isNumber || (string == NSNumberFormatter().decimalSeparator && textField.text?.containsString(string) == false) } 

El siguiente es el código que utilicé en Swift 3.0, adaptado del código del Sr. H. Las diferencias son porque:

a) La statement de la función de delegado ha cambiado en Swift 3.0. Nueva statement aquí

b) La statement NSCharacterSet ha cambiado.

 func textField(_ shouldChangeCharactersIntextField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { let inverseSet = NSCharacterSet(charactersIn:"0123456789").inverted let components = string.components(separatedBy: inverseSet) let filtered = components.joined(separator: "") return string == filtered } 

He editado la versión de Raj Joshi para permitir un punto o una coma:

 func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { let inverseSet = CharacterSet(charactersIn:"0123456789").inverted let components = string.components(separatedBy: inverseSet) let filtered = components.joined(separator: "") if filtered == string { return true } else { if string == "." || string == "," { let countDots = textField.text!.components(separatedBy:".").count - 1 let countCommas = textField.text!.components(separatedBy:",").count - 1 if countDots == 0 && countCommas == 0 { return true } else { return false } } else { return false } } } 
 func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { let textString = (textField.text! as NSString).replacingCharacters(in: range, with: string) if textField == self.phoneTextField && string.characters.count > 0{ let numberOnly = NSCharacterSet.decimalDigits let strValid = numberOnly.contains(UnicodeScalar.init(string)!) return strValid && textString.characters.count <= 10 } return true } 

en el código anterior está trabajando en swift 3
NSCharacterSet. dígitos decimales
También usas solo letras
NSCharacterSet. Letras
y mayúsculas, minúsculas y alfanuméricos, espacios en blanco se usa el mismo código o Ver el enlace

Aquí hay una solución simple, necesita conectar el evento “Edición modificada” a este método en su controlador

Swift 4

 @IBAction func valueChanged(_ sender: UITextField) { if let last = sender.text?.last { let zero: Character = "0" let num: Int = Int(UnicodeScalar(String(last))!.value - UnicodeScalar(String(zero))!.value) if (num < 0 || num > 9) { //remove the last character as it is invalid sender.text?.removeLast() } } } 

Extienda su controlador de vista de esta manera:

 class MyViewController: UIViewController, UITextFieldDelegate 

En la función viewDidLoad se extiende a su campo de texto de esta manera:

 myTextField.delegate = self 

Y luego usa la siguiente función:

 func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { let isNumber = CharacterSet.decimalDigits.isSuperset(of: CharacterSet(charactersIn: string)) let withDecimal = ( string == NumberFormatter().decimalSeparator && textField.text?.contains(string) == false ) return isNumber || withDecimal } 

Esto ahora se asegurará de que el usuario pueda ingresar solo dígitos decimales.

Swift 4 + acepta solo el número y acepta un separador

 Swift 2.0 func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { let inverseSet = NSCharacterSet(charactersInString:"0123456789").invertedSet let components = string.componentsSeparatedByCharactersInSet(inverseSet) let filtered = components.joinWithSeparator("") return string == filtered } 

Esta es una versión más legible que hará “0-9” más “.”:

 func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { let existingTextHasDecimal = textField.text?.rangeOfString(".") let replacementTextHasDecimal = string.rangeOfString(".") let replacementTextAllCharacters = NSCharacterSet(charactersInString: string) let replacementTextOnlyDigits = NSCharacterSet.decimalDigitCharacterSet().isSupersetOfSet(replacementTextAllCharacters) if replacementTextHasDecimal != nil && existingTextHasDecimal != nil { return false }else{ if replacementTextOnlyDigits == true { return true }else if replacementTextHasDecimal != nil{ return true }else{ return false } } } 
 func isValidNumber(str:String) -> Bool{ if str.isEmpty { return false } let newChar = NSCharacterSet(charactersInString: str) let boolValid = NSCharacterSet.decimalDigitCharacterSet().isSupersetOfSet(newChar) if boolValid{ return true }else{ let lst = str.componentsSeparatedByString(".") let newStr = lst.joinWithSeparator("") let currentChar = NSCharacterSet(charactersInString: newStr) if lst.count == 2 && !lst.contains("") && NSCharacterSet.decimalDigitCharacterSet().isSupersetOfSet(currentChar){ return true } return false } } 

Ponga esta función en su método “Enviar” o “Guardar” si hay uno.

Puede usar shouldChangeCharactersInRange junto con el método de extensión String para verificar si la cadena de entrada es numérica o no.

 extension String { var isNumber : Bool { get{ return !self.isEmpty && self.stringWithoutWhitespaces.rangeOfCharacter(from: CharacterSet.decimalDigits.inverted) == nil } } var stringWithoutWhitespaces: String { return self.replacingOccurrences(of: " ", with: "") } } //Mark: shouldChangeCharactersInRange func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { // return true if the string only contains numeric characters let isValid = string.stringWithoutWhitespaces.isNumber return valid } 

Solución muerta simple para Números Double (tenga en cuenta que esta no es la mejor solución fácil de usar), en su delegado UITextFieldDelegate :

 func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { guard let currentString = textField.text as NSString? else { return false } let newString = currentString.replacingCharacters(in: range, with: string) return Double(newString) != nil } 

Puede usar este código si desea permitir el separador decimal y / o números negativos. Pero este código permite el ejemplo: “34.” (separador decimal al final) al cambiar el texto. Por lo tanto, debe agregar algunos ejemplos de código: textFieldShouldReturn o textFieldShouldEndEditing delegar funciones.

El código escrito en Swift 4 pero supongo que esto es compatible con Swift 3.

 func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { guard let text = textField.text else { return true } let replaced = (text as NSString).replacingCharacters(in: range, with: string) let decimalSeparator = NSLocale.current.decimalSeparator ?? "" // When user wants to delete las character if replaced == "" || replaced == "-" || replaced == "-0" { textField.text = "0" return false } // When text contains 0 before replace except "0." if replaced != "0" + decimalSeparator && replaced.hasPrefix("0") && text.underestimatedCount == 1 { textField.text = replaced.substring(from: replaced.index(after: replaced.startIndex)) return false } // When user wants to delete minus sign if text.hasPrefix("-") && text.substring(from: text.index(after: text.startIndex)) == replaced { return false } // When user wants to delete before decimal separator if replaced.hasPrefix(decimalSeparator) || replaced.hasPrefix("-" + decimalSeparator) { return false } // When user wants to add zero the beginning of number... but allowing "0." or "-0." numbers let testReplaced = replaced.hasPrefix("-") ? replaced.substring(from: replaced.index(after: replaced.startIndex)) : replaced if testReplaced.count >= 2 && testReplaced.hasPrefix("0") && !testReplaced.hasPrefix("0" + decimalSeparator) { return false } // Every other cases let allowDecimal = self.allowFloat ? (decimalSeparator == "." ? "\\.?" : decimalSeparator + "?") : "" let allowSign = self.allowSigned ? "-?" : "" let pattern = "\(allowSign)[0-9]+\(allowDecimal)([0-9]+)?" do { let regexRange = (replaced as NSString).range(of: replaced) let regex = try NSRegularExpression(pattern: pattern, options: []) let matches = regex.matches(in: replaced, options: [], range: regexRange) return matches.count == 1 && matches.first!.range == regexRange } catch {} return false } 

Si no desea permitir números decimales o negativos, debe reemplazar la variable de remolque con la siguiente línea

 let allowDecimal = "" let allowSign = "" 

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 } 

Para permitir algunos charactores

 func CheckAddress(string:String) -> Bool { let numberOnly = NSCharacterSet.init(charactersIn: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-@,&#/") let stringFromTextField = NSCharacterSet.init(charactersIn: string) return numberOnly.isSuperset(of: stringFromTextField as CharacterSet) } print("\(CheckAddress(string: "123"))") //True print("\(CheckAddress(string: "asdf-"))") //True print("\(CheckAddress(string: "asd123$"))") //false 

Primero agregue delegate y keyBoradType of textField

textField.delegate=self; textField.keyboardType = UIKeyboardTypeNumberPad;

Que tener que usar el método textField.delegate como tal –

 - (BOOL) textField: (UITextField *)theTextField shouldChangeCharactersInRange:(NSRange)range replacementString: (NSString *)string { if (!string.length) { return YES; } if ([string intValue]) { return YES; } return NO; } 

La respuesta de Cian actualizada arriba a Swift 3:

func textField(textField: UITextField,shouldChangeCharactersInRange range: NSRange,replacementString string: String) -> Bool { let newCharacters = NSCharacterSet(charactersIn: string) let boolIsNumber = NSCharacterSet.decimalDigits.isSuperset(of:newCharacters as CharacterSet) if boolIsNumber == true { return true } else { if string == "." { let countdots = textField.text!.components(separatedBy:".").count - 1 if countdots == 0 { return true } else { if countdots > 0 && string == "." { return false } else { return true } } } else { return false } } }