ios iphone swift ipad uitextfield

ios - uitextfielddelegate



¿Cómo restringir UITextField para que solo tome números en Swift? (30)

Primero, debe heredar la clase UITextFieldDelegate con su propia clase

class ViewController: UIViewController, UITextFieldDelegate {

2º agregar un IBOutlet

@IBOutlet weak var firstName: UITextField!

Tercero, debe asegurarse de que este objeto esté usando

override func viewDidLoad() { super.viewDidLoad() firstName.delegate = self } func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { if textField == firstName { let allowedCharacters = "1234567890" let allowedCharacterSet = CharacterSet(charactersIn: allowedCharacters) let typedCharacterSet = CharacterSet(charactersIn: string) let alphabet = allowedCharacterSet.isSuperset(of: typedCharacterSet) return alphabet } }

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

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


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) }


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 } } }


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 }


Aquí hay una solución más limpia:

guard CharacterSet(charactersIn: "123456789").isSuperset(of: CharacterSet(charactersIn: string)) else { return false } return true

Para decimales solo agregue . , ejemplo 123456789.


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() } } }


Como si no hubiera suficientes respuestas, aquí está la mía. Creo que todos los ejemplos permitidos para los separadores decimales tienen fallas en la localización, los espacios de retroceso o 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 }


Creo que puede forzar el cambio del tipo de teclado mediante la implementación del 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 } } }


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 declaración de función delegada ha cambiado en Swift 3.0. Nueva declaración aquí

b) La declaración 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 }


En swift 4.1 y Xcode 9.4.1

Agregue UITextFieldDelegate a su clase

class YourViewController: UIViewController, UITextFieldDelegate

Luego escriba este código en su viewDidLoad ()

mobileNoTF.delegate = self

Escriba esta función delegada 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 }


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 } } }


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 use 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 asegurará que el usuario pueda ingresar solo dígitos decimales.

Swift 4 + acepta solo números y acepta un separador


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 } } }


Para permitir algunos personajes

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


Para permitir solo números y un solo 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) }


Probado en swift 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 }


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

El código escrito en Swift 4 pero supongo que 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 = ""


Puede usar shouldChangeCharactersInRange junto con el método de extensión String para verificar si la cadena de entrada es número 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 }


Realmente había hecho esto cuando estaba trabajando en el libro 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 "." además es más complicado ya que solo puedes permitir un "."


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 forma 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 }


Solución simple muerta 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 }


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 } } }


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 }


Usar formateador de números

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 }


Solución solo para iPhone

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

Por ejemplo, un teclado solo numérico.

Como esta captura de pantalla:

Ipad

El iPad no es compatible con el teclado numérico, por lo que sus opciones son no admitir el iPad, validar el envío de campo o seguir una de las otras sugerencias aquí para crear comportamientos sanos mientras se ejecuta en un iPad.


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 existe.


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 los 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.


func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { if let numRange = string.rangeOfCharacterFromSet(NSCharacterSet.letterCharacterSet()) { return false } else { return true } }


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á funcionando en Swift 3
NSCharacterSet. dígitos decimales
También usas letras solamente
NSCharacterSet. Letras
y mayúsculas, minúsculas y alfanuméricas, espacios en blanco se utiliza el mismo código o Ver el enlace


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 }