Dans Swift, j'essaie de créer un champ de texte permettant d'activer un bouton, mais uniquement lorsque le champ de texte contient un entier. Comment puis-je faire ceci?
UITextFieldDelegate
en ajoutant UITextFieldDelegate
à la déclaration de classe.IBOutlet
s pour votre champ de texte et votre bouton.viewDidLoad
, définissez la propriété isEnabled
de votre bouton sur false
et définissez self
en tant que textField.delegate
.textField:shouldChangeCharactersInRange:replacementString:
. Cette méthode sera appelée chaque fois que votre champ de texte est modifié. Là, vérifiez si le champ de texte actuel est converti en Int
en appelant toInt()
et activez/désactivez votre bouton comme vous le souhaitez.Voici le code:
class ViewController: UIViewController, UITextFieldDelegate {
@IBOutlet weak var textField: UITextField!
@IBOutlet weak var button: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
button.isEnabled = false
textField.delegate = self
}
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
// Find out what the text field will be after adding the current edit
let text = (textField.text as NSString).stringByReplacingCharactersInRange(range, withString: string)
if let intVal = text.toInt() {
// Text field converted to an Int
button.isEnabled = true
} else {
// Text field is not an Int
button.isEnabled = false
}
// Return true so the text field will be changed
return true
}
}
EDIT: Dans Swift 3, la propriété enabled
est remplacée par isEnabled
.
Deux choses:
Spécifiez le type de clavier pour afficher uniquement le pavé numérique. Donc, définissez la keyboardType
sur .numberPad
. Cela ne suffit toutefois pas pour empêcher l'utilisateur de saisir des caractères non valides dans le champ de texte. Par exemple, l'utilisateur peut toujours coller du texte ou changer de clavier lorsqu'il utilise un iPad.
Spécifiez le délégué du champ de texte et implémentez shouldChangeCharactersInRange
qui n'acceptera aucun autre caractère que les chiffres 0
si 9
:
class ViewController: UIViewController, UITextFieldDelegate {
@IBOutlet weak var textField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// you can set the following two properties for the text field in Interface Builder, if you'd prefer
textField.delegate = self
textField.keyboardType = .numberPad
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let invalidCharacters = CharacterSet(charactersIn: "0123456789").inverted
return string.rangeOfCharacter(from: invalidCharacters) == nil
}
// or, alternatively:
//
// func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
// return string.range(of: "^\\d*$", options: .regularExpression) != nil
// }
}
Pour le rendu de Swift 2, voir la révision précédente de cette réponse.
Swift 4: Que diriez-vous d'une simple guard
et typecasting to Int
comme ci-dessous
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
guard let _ = Int(string) else {
button.isEnabled = false
return true
}
button.isEnabled = true
return true
}
Chaque champ de texte a une keyboardType
. Vous pouvez définir UIKeyboardType.NumbersAndPunctuation
pour n’afficher que les chiffres et conserver la clé de retour (interface utilisateur défensive). Vous pouvez ensuite utiliser scanInt()
de NSScanner
pour vérifier si textField.text est un entier valide.
Vous devez d'abord hériter de la classe UITextViewDelegate avec votre propre propriétaire classe
class ViewController: UIViewController, UITextViewDelegate {
2ème ajouter un IBOutlet
@IBOutlet weak var firstName: UITextField!
3ème vous devez vous assurer que cet objet utilise
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
}
}
En ce qui concerne accepter les retours à l’arrière et autres caractères de contrôle, j’ai utilisé la méthode suivante:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if string.isEmpty { // This is for accept control characters
return true
}
let numericRegEx = "[0-9]"
let predicate = NSPredicate(format:"SELF MATCHES %@", numericRegEx)
let newText = (textFieldCount.text as! NSString).replacingCharacters(in: range, with: string)
return predicate.evaluate(with: string)
}
Si vous voulez qu'il accepte également les points flottants, il suffit de changer RegEx en
let numericRegEx = "[.0-9]"
Si la taille du texte est limitée à 10, changez la dernière ligne comme suit:
return predicate.evaluate(with: string) && newText.count < 10
Vous pouvez utiliser NSScanner pour faire cela, voici ce qui pourrait être utile d'essayer de l'utiliser et laissez-moi savoir s'il y a des problèmes.
if( [[NSScanner scannerWithString:@"-123.4e5"] scanFloat:NULL] )
NSLog( @"\"-123.4e5\" is numeric" );
else
NSLog( @"\"-123.4e5\" is not numeric" );
if( [[NSScanner scannerWithString:@"Not a number"] scanFloat:NULL] )
NSLog( @"\"Not a number\" is numeric" );
else
NSLog( @"\"Not a number\" is not numeric" );
suivez le lien http://rosettacode.org/wiki/Determine_if_a_string_is_numeric#Objective-C . Essayez-le dans Swift, les noms de classe et de méthode sont les mêmes.
Voici une méthode réutilisable pour Cocoa, Swift 4.1
1- Créez un fichier avec la classe NSTextFieldFormated ci-dessous
2- Dans l'inspecteur Identity, modifiez la classe CustomClass du champ à formater en NSTextFieldFormated.
3- Dans l'inspecteur 'Attributs', définissez les valeurs 'int Min Value', 'int Max Value' et 'int Length' du champ à formater.
4- Glissez et déposez un objet (NSObject) de la bibliothèque Object vers la scène View Controller dans la liste des objets du générateur d'interface de contour (à gauche de la zone de dessin de l'interface).
5- Dans 'Identity Inspector', définissez la 'CustomClass class' sur NSTextFieldFormated
6- Sélectionnez le champ à formater et dans l'inspecteur de connexions, définissez le délégué de champ sur le nouvel objet 'Text Field Formatted' dans 'View Controller Scene'.
Ensuite, le NSTextField est maintenant formaté.
class NSTextFieldFormated: NSTextField, NSControlTextEditingDelegate {
private struct Digit {
var minValue: Int? // minimum
var maxValue: Int? // maximum
var digitAmt: Int? // minimumIntegerDigits
}
private var digit = Digit()
//-Integer
@IBInspectable var intMinValue: Int {
get {
guard let minVal = digit.minValue else { return Int.min }
return minVal
}
set { digit.minValue = newValue ; setFormatter() }
}
@IBInspectable var intMaxValue: Int {
get {
guard let maxVal = digit.maxValue else { return Int.max }
return maxVal
}
set { digit.maxValue = newValue ; setFormatter() }
}
@IBInspectable var intLenght: Int {
get {
guard let length = digit.digitAmt else { return -1 }
return length
}
set { digit.digitAmt = newValue ; setFormatter() }
}
private func setFormatter() {
let lformatter = IntegerFormatter()
lformatter.minimum = intMinValue as NSNumber
lformatter.maximum = intMaxValue as NSNumber
if intLenght != -1 {
lformatter.minimumIntegerDigits = intLenght
}
self.formatter = lformatter
}
class IntegerFormatter: NumberFormatter {
override func isPartialStringValid(_ partialString: String,
newEditingString newString: AutoreleasingUnsafeMutablePointer<NSString?>?,
errorDescription error: AutoreleasingUnsafeMutablePointer<NSString?>?) -> Bool {
if partialString.rangeOfCharacter(from: CharacterSet.decimalDigits.inverted) != nil {
NSSound.beep()
return false
}
return Int(partialString) != nil
}
}
override func controlTextDidChange(_ notification: Notification) {
if let textField = notification.object as? NSTextFieldFormated {
if let val = Int(textField.stringValue) {
//print(">4")
if val > textField.intMaxValue {
textField.stringValue = String(textField.intMaxValue)
}
}
}
}
}