Erlaube nur Zahlen für die Eingabe von UITextField


82

Das iPad verfügt nicht über eine "Numpad" -Tastatur wie das iPhone / der iPod.

Ich möchte herausfinden, wie ich die Tastatur des Benutzers so einschränken kann, dass nur die Werte 0 bis 9 akzeptiert werden.

Ich würde mir vorstellen, UITextFields "shouldChangeCharactersInRange" zu verwenden, aber ich weiß nicht, wie ich es am besten implementieren kann.


Ich habe ein Tutorial erstellt, wie dies mit herunterladbarem Projektquellcode erreicht werden kann. Hier: xcodenoobies.blogspot.com/2013/12/…
GeneCode

Antworten:


85

Auf diese Weise können Sie das Problem in einem SSN-Überprüfungsfeld behandeln. Sie können die maximale Länge ändern und ifbei Bedarf die Anweisungsprüfung für den Tastaturtyp entfernen .

Es gibt auch eine Logik zum Unterdrücken der Warnungen für die maximale Länge, wenn der Benutzer tippt, anstatt Daten einzufügen.

Im Kontext dieses Codes gibt presentAlert()/presentAlert:es nur einige grundlegende Funktionen, die eine UIAlertController(oder eine Legacy- UIAlertView) Funktion unter Verwendung der übergebenen Nachrichtenzeichenfolge darstellen.

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

Ziel c

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

2
Vielen Dank! Der Abschnitt "Ungültige Zeichen aus der Eingabe entfernen, wenn die Tastatur ein Nummernblock ist" half bei der Beantwortung meiner Frage!
Demasterpl

@Gargo Die Frage besagt ausdrücklich, dass die einzigen zulässigen Werte die Ziffern 0 bis 9 sein sollten. Das Punktzeichen fällt nicht unter diese Anforderungen. Um das Punktzeichen zuzulassen, kann man hier die Antwort von Aje sehen .
Beltalowda

bereits verwendet, aber es lässt das Problem mit führenden Nullen
Gargo

@Gargo können Sie etwas Ähnliches wie das zum Erkennen anderer Punktzeichen verwenden und nur dann Ja für ein Nullzeichen zurückgeben, wenn: das Textfeld derzeit leer ist, wenn die Einfügemarke auf Index 0 liegt und das nächste Zeichen ein Punkt ist, oder Wenn sich die Einfügemarke an einem Index befindet, der größer als der eines vorhandenen Punktzeichens ist. Zumindest wäre dies eine Möglichkeit, um sicherzustellen, dass die eingegebene Null kein führendes Nullproblem verursacht.
Beltalowda

26

Mit diesem Code können Sie nur Zahlen in textField zulassen.

Stellen Sie zuvor den Delegaten für textField ein

      textFieldName.delegate=self;

oder

      [textFieldName setDelegate:self];

Verwenden Sie diesen Code, um nur Ziffern für textField zuzulassen

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

5
Übrigens, für andere, die diesen Code verwenden, wird [string intValue]0 für @ "0" zurückgegeben - if ([string intValue])wird also für @ "0" nicht erfüllt. Besser zu benutzenif ([string rangeOfCharacterFromSet:[[NSCharacterSet decimalDigitCharacterSet] invertedSet]].location != NSNotFound)
CharlesA

2
@".".intValueist 0. Und @"0".intValueist auch 0.
Jaybo

Um die anderen Kommentare hier zu verdeutlichen: Mit diesem Code kann der Benutzer kein Nullzeichen ( 0) eingeben .
Beltalowda

21

Versuchen Sie dies, um Probleme beim Löschen von Textfeldern zu vermeiden

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
}

2
Sie können die Delegatenmethode vereinfachen und sind gerade gegangenreturn guard CharacterSet(charactersIn: "0123456789").isSuperset(of: CharacterSet(charactersIn: string))
Hamsternik

18

Sehr spezifische Schritte für Swift-Code

Sie können eine Logik bereitstellen, die die Eingabe des Textfelds in die func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> BoolMethode einschränkt , indem Sie das UITextFieldDelegateProtokoll implementieren .

Aus Gründen der Übersichtlichkeit wird bei diesen Schritten davon ausgegangen, dass Ihr Storyboard einen View Controller mit einem Textfeldobjekt enthält , das nur Ziffern akzeptieren sollte.

  1. Erstellen Sie eine benutzerdefinierte Klasse für den erweiterten View Controller UIViewController. Stellen Sie sicher, dass sich die Szene in Ihrem Storyboard auf die benutzerdefinierte Klasse bezieht, indem Sie den benutzerdefinierten Klassenwert im Identitätsinspektor von Xcode festlegen.

    import UIKit
    class YourCustomController: UIViewController {
        override func viewDidLoad() {        
            super.viewDidLoad()
        }
    }
  2. Erstellen Sie einen Ausgang aus dem Textfeld Ihrer Szene zu Ihrem benutzerdefinierten View Controller.

    class YourCustomController: UIViewController {
        @IBOutlet weak var numberField: UITextField!
        ...
    }
  3. Wenden Sie das UITextFieldDelegateProtokoll in Ihrem benutzerdefinierten Ansichtscontroller an.

    class YourCustomController: UIViewController, UITextFieldDelegate {
        ...
    }
  4. viewDidLoadWeisen Sie in der Methode Ihres benutzerdefinierten Ansichtscontrollers den Delegaten Ihres Textfelds Ihrer benutzerdefinierten Ansichtscontrollerklasse zu.

    override func viewDidLoad() {        
        super.viewDidLoad()
        numberField.delegate = self
    }
  5. Fügen Sie die UITextFieldDelegates‘ func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> BoolMethode.

    Nachdem Sie Ihren benutzerdefinierten Ansichtscontroller numberFieldim vorherigen Schritt zum Delegaten gemacht haben, wird diese Methode jedes Mal aufgerufen, wenn ein Benutzer ein Zeichen in das Textfeld eingibt. Wenn Ihre Methode zurückgibt true, bleibt das Zeichen im Textfeld. Wenn Ihre Methode zurückgibt, bleibt falsedas Zeichen nicht im Textfeld.

    Der stringParameter ist das vom Benutzer eingegebene Zeichen. Wenn das stringZeichen in ein konvertiert werden kann, Intliegt es zwischen 0 und 9; Andernfalls handelt es sich um ein Nicht-Zahlenzeichen.

    class YourCustomController: UIViewController, UITextFieldDelegate {
        ...
        func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    
            return Int(string) != nil
        }
    }

(Siehe unten für den Vollbild-Controller-Code.)


Beispiel View Controller mit nur Ziffern Textfeld

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

Beispiel View Controller mit einem dezimalen Textfeld

Wenn Sie eine Dezimalzahl unterstützen möchten, nutzen Sie NSNumberFormatter. Die Unterschiede finden Sie in den Codekommentaren.

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

2
Dies ist gut, hat aber eine kleine Anpassung vorgenommen, da Sie damit nichts im Feld löschen können, ohne nach leeren Zeichenfolgen zu suchen. Ich habe auch die Möglichkeit für Negative hinzugefügt, indem ich das erste Zeichen if (string == "-" && range.location == 0) || überprüft habe string == "" {return true} return string.toInt ()! = nil
ickydime

return string.toInt() != nil Lief wie am Schnürchen. Vielen Dank!
CalZone

Hinweis in Swift 2 musste ich dies aufreturn Int(string) != nil
nevster

@nevster Danke für den Kommentar! Ich denke, die meisten Swift-Entwickler sind umgezogen oder werden auf Swift 2 und höher umsteigen. Daher habe ich die Antwort aktualisiert, um sie an die String-zu-Int-Konvertierung von Swift 2 anzupassen.
warum weiß

7
Eine weitere Änderung, die ich vornehmen musste - der Löschschlüssel funktionierte nicht mehr! Also habe ich es geändert inreturn string == "" || Int(string) != nil
nevster

9
- (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;
}

1
Dies funktioniert gut für den Bruch juste, den Sie benötigen, um den richtigen newString zu ändern: NSString * newString = [textField.text stringByReplacingCharactersInRange: range withString: string];
Idali

7

Ich habe das angewendet und es funktioniert !!

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

1
Um "." Hinzuzufügen, ersetzen Sie if (character < 48) return NO; // 48 unichar for 0 if (character > 57) return NO; // 57 unichar for 9durch if ((character < 48 || character > 57) && character != 46)Ich würde zusätzlich empfehlen, Sie charactermit einer hexadezimalen Darstellung der Zahlen zu vergleichen , da Hexadezimalzahlen unter diesen Umständen am häufigsten verwendet werden. Dhif ((character < 0x30 || character > 0x39) && character != 0x2E)
Jacob R

2
NSString* val = [[textField text] stringByReplacingCharactersInRange:range withString:string];
    NSCharacterSet *allowedCharacterSet = [NSCharacterSet decimalDigitCharacterSet];
    if ([[string componentsSeparatedByCharactersInSet:[allowedCharacterSet invertedSet]] count] > 1 || [val length] > 5) {
        return NO;
    }

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

1

In Swift:

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        return string.isEmpty || Int(string) != nil
    }

1

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

Sie können jetzt nur noch auf 1234567890 tippen


0

Halten Sie unterschiedliche Präsentationsdaten von der internen Darstellung fern. Es gibt einen einfacheren Weg. Lass NSNumberFormatterden Job machen:

 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]]];

0

Wenn Sie mein Spezifikationsmuster verwenden, sieht der Code so aus

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
}

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

Hallo @MarcoAlmeida werfen Sie einen Blick auf mein Framework SwiftyFORM, es kann live validieren Text, github.com/neoneye/SwiftyFORM
neoneye

0

Ich habe die Antwort von @ iDev geändert, um für Digitale und "." Zu arbeiten:

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

0

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

-1

Verwenden Sie diesen Code:

NSString* val = [[textField text] stringByReplacingCharactersInRange:range withString:string];
NSCharacterSet *allowedCharacterSet = [NSCharacterSet decimalDigitCharacterSet];
if ([[string componentsSeparatedByCharactersInSet:[allowedCharacterSet invertedSet]] count] > 1 || [val length] > 5) {
    return NO;
}
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.