web-dev-qa-db-fra.com

Comment puis-je déclarer qu'un champ de texte ne peut contenir qu'un entier?

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?

20
user4241521
  1. Faites de votre contrôleur de vue une UITextFieldDelegate en ajoutant UITextFieldDelegate à la déclaration de classe.
  2. Ajoutez IBOutlets pour votre champ de texte et votre bouton.
  3. Dans viewDidLoad, définissez la propriété isEnabled de votre bouton sur false et définissez self en tant que textField.delegate.
  4. Implémentez la méthode 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.

15
vacawama

Deux choses: 

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

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

52
Rob

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

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.

1
mumush

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



      }
  }
1
akbar khan

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
0

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.

0
yashwanth77

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)
                }
            }
        }
    }
}
0
Luc-Olivier