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?

Karthik Kumar
quelle
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
}
Herr H.
quelle
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)
  }
Hiren Panchal
quelle
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
}
iOS
quelle
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
        }
    }
}
Cian
quelle
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.

Jamil Hasnine Tamim
quelle
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
        }
    }
}
Raj Joshi
quelle
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 .

ndmeiri
quelle
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
 }
SPatel
quelle
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

Aftab Ahmed
quelle
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()
        }
    }
}
shbli
quelle
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
}

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


      }
  }
Akbar Khan
quelle
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.

Farhad
quelle
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.

Jagadeesh K.
quelle
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.

sgib
quelle
2
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    if let numRange = string.rangeOfCharacterFromSet(NSCharacterSet.letterCharacterSet()) {
        return false
    } else {
        return true
    }
   }
Likarson
quelle
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)
}
hprione
quelle
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

Ramprasath Selvam
quelle
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
    }
Tony
quelle
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
        }
    } 
}
Lukas
quelle
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
}
David
quelle
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

}
ChinLoong
quelle
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
        }
    }
}
Matthijs
quelle
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
Ilesh P.
quelle
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

  }
Edison
quelle
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
        }
    }
}
Wütend
quelle
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.

den330
quelle
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
}
Suhit Patil
quelle
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
}
Tomasz Wójcik
quelle