El iPad no tiene un teclado "Numpad" como el iPhone / iPod.
Estoy buscando cómo puedo restringir el teclado del usuario para que solo acepte valores del 0 al 9.
Me imagino usando "shouldChangeCharactersInRange" de UITextField pero no sé la mejor manera de implementarlo.
ios
ipad
cocoa-touch
uitextfield
uikeyboard
Demasterpl
fuente
fuente
Respuestas:
Así es como puede manejar el problema en un campo de verificación SSN, puede modificar la longitud máxima y eliminar la
if
declaración que verifica el tipo de teclado si es necesario.También existe una lógica para suprimir las alertas de longitud máxima cuando el usuario está escribiendo en lugar de pegar datos.
Dentro del contexto de este código,
presentAlert()/presentAlert:
es solo una función básica que presenta unUIAlertController
(o un legadoUIAlertView
) usando la cadena de mensaje pasada.Rápido 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 }
C objetivo
// 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; }
fuente
Puede usar este código para permitir solo números en textField.
Antes de que establezca delegado para textField
textFieldName.delegate=self;
o
[textFieldName setDelegate:self];
Luego use este código para permitir solo dígitos para 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; }
fuente
[string intValue]
devuelve 0 para @ "0", porif ([string intValue])
lo que no se cumple para @ "0". Mejor usoif ([string rangeOfCharacterFromSet:[[NSCharacterSet decimalDigitCharacterSet] invertedSet]].location != NSNotFound)
@".".intValue
es 0. Y también@"0".intValue
es 0.0
).Intente esto para evitar problemas de limpieza del campo de texto
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 }
fuente
return guard CharacterSet(charactersIn: "0123456789").isSuperset(of: CharacterSet(charactersIn: string))
Pasos muy específicos para el código Swift
Puede proporcionar lógica que restrinja la entrada del campo de texto en el
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool
método implementando elUITextFieldDelegate
protocolo.En aras de la claridad, estos pasos asumen que su guión gráfico contiene un controlador de vista con un objeto de campo de texto que solo debe aceptar dígitos.
Cree una clase personalizada para el controlador de vista que se extiende
UIViewController
. Asegúrese de que la escena en su guión gráfico se refiera a la clase personalizada estableciendo el valor de la clase personalizada en el Inspector de identidad de Xcode.import UIKit class YourCustomController: UIViewController { override func viewDidLoad() { super.viewDidLoad() } }
Cree una salida desde el campo de texto de su escena a su controlador de vista personalizado.
class YourCustomController: UIViewController { @IBOutlet weak var numberField: UITextField! ... }
Aplica el
UITextFieldDelegate
protocolo en tu controlador de vista personalizado.class YourCustomController: UIViewController, UITextFieldDelegate { ... }
En el
viewDidLoad
método de su controlador de vista personalizado , asigne el delegado de su campo de texto a su clase de controlador de vista personalizado.override func viewDidLoad() { super.viewDidLoad() numberField.delegate = self }
Añadir la
UITextFieldDelegate
'sfunc textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool
método.Como resultado de hacer que su controlador de vista personalizado sea el
numberField
delegado en el paso anterior, este método se llamará cada vez que un usuario ingrese un carácter en el campo de texto. Si su método regresatrue
, el carácter permanecerá en el campo de texto. Si su método regresafalse
, el carácter no permanecerá en el campo de texto.El
string
parámetro es el carácter que ingresa el usuario. Si elstring
carácter se puede convertir en un,Int
entonces está entre 0 y 9; de lo contrario, es un carácter no numérico.class YourCustomController: UIViewController, UITextFieldDelegate { ... func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { return Int(string) != nil } }
(Consulte a continuación el código del controlador de vista completa).
Ejemplo de controlador de vista con campo de texto de solo dígitos
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 } }
Ejemplo de controlador de vista con un campo de texto decimal
Si desea admitir un número decimal, aproveche
NSNumberFormatter
. Consulte los comentarios del código para conocer las diferencias.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 } }
fuente
return string.toInt() != nil
Trabajado como un encanto. ¡Gracias!return Int(string) != nil
return string == "" || Int(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; }
fuente
¡Apliqué esto y funciona!
-(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; }
fuente
if (character < 48) return NO; // 48 unichar for 0 if (character > 57) return NO; // 57 unichar for 9
con.if ((character < 48 || character > 57) && character != 46)
También le recomendaría que comparecharacter
con representaciones hexadecimales de los números, ya que los hexadecimales se usan más comúnmente en estas circunstancias. Es decirif ((character < 0x30 || character > 0x39) && character != 0x2E)
NSString* val = [[textField text] stringByReplacingCharactersInRange:range withString:string]; NSCharacterSet *allowedCharacterSet = [NSCharacterSet decimalDigitCharacterSet]; if ([[string componentsSeparatedByCharactersInSet:[allowedCharacterSet invertedSet]] count] > 1 || [val length] > 5) { return NO; }
fuente
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; }
fuente
En Swift:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { return string.isEmpty || Int(string) != nil }
fuente
rápido 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) }
Ahora puede tocar solo 1234567890
fuente
Mantenga distintos datos de presentación de la representación interna. Existe una forma más sencilla. Deja
NSNumberFormatter
hacer el trabajo: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]]];
fuente
Si usa mi patrón de especificación , el código se ve así
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 }
fuente
He modificado la respuesta de @ iDev para que funcione con digitales y ".":
-(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; }
fuente
rápido 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 }
fuente
Utilice este código:
NSString* val = [[textField text] stringByReplacingCharactersInRange:range withString:string]; NSCharacterSet *allowedCharacterSet = [NSCharacterSet decimalDigitCharacterSet]; if ([[string componentsSeparatedByCharactersInSet:[allowedCharacterSet invertedSet]] count] > 1 || [val length] > 5) { return NO; }
fuente