Wie kann ich UITextField so einschränken, dass in Swift nur Zahlen verwendet werden?


73

Ich möchte, dass der Benutzer nur numerische Werte in a eingibt UITextField. Auf dem iPhone können wir die numerische Tastatur anzeigen, aber auf dem iPad kann der Benutzer zu einer beliebigen Tastatur wechseln.

Gibt es eine Möglichkeit, den Benutzer daran zu hindern, nur numerische Werte in a einzugeben UITextField?


Sie müssen den eingegebenen Text ändern.
Blind Ninja

Ja, aber im iPad kann der Benutzer das Alphabet auch dann eingeben, wenn wir die numerische Tastatur eingestellt haben

Was meinst du mit dem Ändern des Textes?


Antworten:


79

Hier sind meine 2 Cent. (Nur auf Swift 2 getestet)

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

}

Dies ist nur ein bisschen strenger. Auch kein Dezimalpunkt.

Ich hoffe es hilft :)

PS: Ich nahm an, Sie haben sich trotzdem um den Delegierten gekümmert.

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

Wie würde ich das UITextfield so einschränken, dass nur Nummern empfangen werden und die Anzahl der Nummern zwischen 6 und 8 begrenzt wird?
Marco Almeida

Sie können einstellen aSet, nur zu seinCharacterSet.decimalDigits.invertedSet
yesthisisjoe

Perfekt für meine Bedürfnisse. Vielen Dank.
Mai Yang

Warum hast du UITextFieldDelegate nicht erwähnt?
user924

Sie sollten auch eine Prüfung hinzufügen, text == ""damit der Benutzer Text rückwärts löschen kann.
Thecoolwinter

79

Lösung für Swift 3.0 und höher

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

4
Ihr View Controller sollte konform sein UITextFieldDelegate, in viewDidLoad putyourNumbersTextField.delegate = self
Manee.OH

Was ist Reichweite?
user924

Warum hast du UITextFieldDelegate nicht erwähnt?
user924

@ user924 Bereich wird von UITextField Delegate-Methode zurückgegeben
Hiren Panchal

@ user924 Erwähnung von UITextFieldDelegate ist Grundvoraussetzung
Hiren Panchal

25

In Swift 4.1 und Xcode 9.4.1

Fügen Sie Ihrer Klasse UITextFieldDelegate hinzu

class YourViewController: UIViewController, UITextFieldDelegate

Dann schreiben Sie diesen Code in Ihre viewDidLoad ()

mobileNoTF.delegate = self

Schreiben Sie diese Textfeld-Delegatenfunktion

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

Wie Binary operator '==' cannot be applied to operands of type 'UITextField' and '() -> ()'
behebe

@iOS, wie geht das? Ich habe alles hinzugefügt, kann aber trotzdem alles eingeben. Das Feld lässt beliebige Zeichen zu und die Funktion textField wird nicht ausgelöst.
Smit

13

Swift 2.0

Nur um Zahlen und ein "." dezimal in 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
        }
    }
}

Danke - das ist großartig (ich suchte nach einer Lösung, um nur 1 "zuzulassen.")
derdida

10

Nur IPhone-Lösung

In jedem UITextField, von dem Sie diese Werte erhalten, können Sie die Art der Tastatur angeben, die angezeigt werden soll, wenn jemand das Textfeld berührt.

ZB eine rein numerische Tastatur.

Wie dieser Screenshot:

Geben Sie hier die Bildbeschreibung ein

Ipad

Das iPad unterstützt die numerische Tastatur nicht. Sie können daher entweder das iPad nicht unterstützen, das Feld nach dem Senden überprüfen oder einem der anderen Vorschläge hier folgen, um dasselbe Verhalten beim Ausführen auf einem iPad zu erzielen.


13
Dies beantwortet die Frage nicht. Selbst bei Verwendung des Nummernblocks würde iOS es einem Benutzer ermöglichen, nicht numerische Werte in das UITextField einzufügen oder iPads das Ausschalten von Tastaturen von numerischen zu ermöglichen.
Rob

Dies ist eine einfache Antwort auf diese Frage !! Keine richtige Antwort! Ich weiß!
Jamil Hasnine Tamim

2
Es ist keine Antwort auf die Frage, weder einfach noch richtig. Die Frage ist nicht , wie der Tastaturtyp geändert werden soll. Die Frage ist , wie die Eingabe eingeschränkt werden kann. Das ist anders.
Rob

Die Frage ist: Wie kann man UITextField so einschränken, dass in Swift nur Zahlen verwendet werden? Wenn Ihr Tastaturtyp ein Nummernblock ist, erfüllt er offensichtlich die Anforderungen.
Jamil Hasnine Tamim

1
Das OP fragt explizit nach einer anderen Lösung als dem Ändern des Tastaturtyps. "Auf dem iPhone können wir die numerische Tastatur anzeigen, aber auf dem iPad kann der Benutzer zu jeder Tastatur wechseln."
Ferdz

9

Akzeptieren Sie Dezimalwerte in Textfeldern mit einem einzelnen (.) Punkt in 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
        }
    }
}

Dies ist die einzige (die auf eine Dezimalstelle beschränkt ist), die ich zum Arbeiten bringen könnte, großartig!
Chris Allinson

Eigentlich habe ich es überarbeitet, um auch ein Komma zuzulassen (gemäß FR)
Chris Allinson

4
Bitte beachten Sie, dass nicht alle Gebietsschemas das "." als Dezimaltrennzeichen. Möglicherweise möchten Sie stattdessen Locale.current.decimalSeparator verwenden.
Volker Voecking

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

Diese Lösung funktioniert auch dann, wenn der Benutzer die Tastatur wechselt oder versucht, eine nicht numerische Zeichenfolge in das Textfeld einzufügen.

Stellen Sie sicher, dass Sie die delegateEigenschaft des entsprechenden Textfelds festlegen .


1
Die Verwendung [string intValue]wie in einer vorherigen Antwort vorgeschlagen funktioniert nicht, da diese Eigenschaft auch dann wahr (ungleich Null) sein kann, wenn sie stringnicht numerische Zeichen enthält. Laut den Dokumenten intValueist 0 nur dann 0, wenn "die Zeichenfolge nicht mit einer gültigen dezimalen Textdarstellung einer Zahl beginnt".
Ndmeiri

5

Verwenden Sie den Zahlenformatierer

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
 }

Vielen Dank! Dieser ist besser als viele andere, weil er Dezimalzahlen erlaubt, aber keine willkürliche Verwendung der Dezimalzahl.
Andy Weinstein

5

Erweitern Sie Ihren View Controller folgendermaßen:

class MyViewController: UIViewController, UITextFieldDelegate

Erweitern Sie in der viewDidLoad-Funktion Ihr Textfeld folgendermaßen:

myTextField.delegate = self

Und dann verwenden Sie die folgende Funktion:

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
}

Dadurch wird sichergestellt, dass der Benutzer nur Dezimalstellen eingeben kann.

Swift 4 + akzeptiert nur die Nummer und akzeptiert ein Trennzeichen


4

Hier ist eine einfache Lösung: Sie müssen das Ereignis "Bearbeiten geändert" mit dieser Methode in Ihrem Controller verbinden

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

Eine großartige Lösung, wenn der Delegat bereits von Rx verwendet wird.
S-K

es wird abstürzen, wenn ich Leerzeichen oder Symbole hinzufüge
karthikeyan

3

Während die meisten dieser Lösungen funktionieren, beachten Sie, dass in einigen Lokalisierungen Dezimalstellen durch ein "," und nicht durch ein "getrennt sind.

Der sauberere Weg, dies zu tun, wäre

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
}

3

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

3

Zunächst müssen Sie die UITextFieldDelegate-Klasse mit Ihrer eigenen Klasse erben

class ViewController: UIViewController, UITextFieldDelegate {

2. Fügen Sie ein IBOutlet hinzu

@IBOutlet weak var firstName: UITextField!

3. Sie müssen sicherstellen, dass dieses Objekt verwendet wird

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


      }
  }

3

Hier ist eine sauberere Lösung:

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

Für Dezimalstellen fügen Sie einfach ein .Beispiel hinzu123456789.


Es ist ein bisschen nett, aber vergleiche mit diesem UITextfiled-Delegaten.
iOS

3

Festlegen der KeyboardType-Eigenschaft: - Number Pad TextField Delegate Bitte schreiben Sie den folgenden Code

  func textField(_ textField: UITextField, shouldChangeCharactersIn 
  range: NSRange, replacementString string: String) -> Bool {

    if textField.text?.count == 0 && string == "0" {
        return false
    }
    return string == string.filter("0123456789".contains)
}

Die Nummer sollte nicht bei 0 beginnen und die Nummer + ve eingeben.


2

Ich hatte dies tatsächlich getan, als ich das Buch der Big Nerd Ranch durchgearbeitet hatte. Meine Lösung lautet:

func textField(textField: UITextField, 
    shouldChangeCharactersInRange range: NSRange, 
    replacementString string: String) -> Bool {

    let newCharacters = NSCharacterSet(charactersInString: string)
    return NSCharacterSet.decimalDigitCharacterSet().isSupersetOfSet(newCharacters)
}

Dies erlaubt nur die Zahlen 0-9, um das "." Dies ist auch komplizierter, da Sie nur ein "" zulassen können.


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

2

Um nur Zahlen und nur einen Dezimaloperator zuzulassen, können Sie diese Lösung verwenden:

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

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

im obigen Code funktioniert in Swift 3
NSCharacterSet. decimalDigits
Sie verwenden auch nur Buchstaben
NSCharacterSet. Buchstaben
und Großbuchstaben, Kleinbuchstaben und alphanumerische Zeichen, Leerzeichen werden mit demselben Code verwendet oder siehe Link


2

Die folgende Lösung hat zwei Vorteile:

  1. Es ist ein einzeiliger Code
  2. Die Eingabe wird so eingeschränkt, dass der Gesamttext im Eingabefeld eine gültige Zahl ist. Andere Lösungen beschränken die Ziffern auf gültige Zahlen, dies führt jedoch dazu, dass der Benutzer "4 ... 5" eingeben kann.
    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        return NumberFormatter().numberFrom(text: (textField.text ?? "") + string) != nil
    }

1

Ich denke, Sie können die Änderung des Tastaturtyps erzwingen, indem Sie das UITextInputTraits-Protokoll (optional var keyboardType) implementieren

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

1

Als ob es nicht genug Antworten gibt, hier ist meine. Ich denke, jedes Beispiel für Dezimaltrennzeichen ist entweder in der Lokalisierung, in den Backspaces oder beim Kopieren / Einfügen fehlerhaft.

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
}

1

Das Folgende ist der Code, den ich in Swift 3.0 verwendet habe, angepasst an den Code von Herrn H. Unterschiede sind, weil:

a) Die Delegate-Funktionsdeklaration wurde in Swift 3.0 geändert. Neue Erklärung hier

b) Die NSCharacterSet-Deklaration hat sich geändert.

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

}

1

Ich habe Raj Joshis Version so bearbeitet, dass ein Punkt oder ein Komma zulässig ist:

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

1

Für einige Zeichen zulassen

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

0
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

  }

0

Dies ist eine besser lesbare Version, die "0-9" plus "."

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

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

Fügen Sie diese Funktion in Ihre Methode "Senden" oder "Speichern" ein, falls vorhanden.


0

Sie können shouldChangeCharactersInRange zusammen mit der String-Erweiterungsmethode verwenden, um zu überprüfen, ob die Eingabezeichenfolge eine Zahl ist oder nicht.

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
}

0

Eine absolut einfache Lösung für DoubleZahlen (denken Sie daran, dass dies nicht die beste benutzerfreundliche Lösung ist) in Ihrem UITextFieldDelegateDelegierten:

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
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.