Дозволити лише цифри для введення UITextField


82

IPad не має клавіатури "Numpad", як у iPhone / iPod.

Я шукаю, як я можу обмежити користувальницьку клавіатуру лише для прийому значень від 0 до 9.

Я міг би уявити, що використовую UITextField "shouldChangeCharactersInRange", але я не знаю найкращого способу його реалізації.


Я зробив підручник про те, як це зробити за допомогою завантажуваного вихідного коду проекту. Тут: xcodenoobies.blogspot.com/2013/12/…
GeneCode

Пройдіть через посилання stackoverflow.com/questions/10734959 / ...
Himanshu padia

Відповіді:


86

Ось як ви можете вирішити проблему в полі перевірки SSN, ви можете змінити максимальну довжину та видалити ifперевірку виписки типу клавіатури, якщо вам потрібно.

Існує також логіка придушення попереджень про максимальну довжину, коли користувач набирає текст, на відміну від вставлення даних.

У контексті цього коду presentAlert()/presentAlert:є лише деяка основна функція, яка представляє UIAlertController(або застарілу UIAlertView) за допомогою переданого рядка повідомлення.

Стрімкий 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
}

Завдання-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
Дякую! Розділ "вилучити недійсні символи з вводу, якщо клавіатура є цифровою клавіатурою" допоміг відповісти на моє питання!
Demasterpl

@Gargo у питанні конкретно зазначено, що єдиними дозволеними значеннями повинні бути цифри від 0 до 9. Символ крапки не підпадає під ці вимоги. Якщо дозволити символ крапки, тут можна побачити відповідь, дану Адже .
Белталовда,

вже використовував його, але це залишає проблему з
початковими

@Gargo ви можете використовувати щось подібне до того, що він має, для виявлення інших символів крапки і повернути так для нульового символу, лише якщо: текстове поле на даний момент порожнє, якщо точка вставки має індекс 0, а наступний символ - крапка, або якщо точка вставки має індекс, більший за індекс існуючого символу періоду. Принаймні, це був би один із способів перевірити, щоб переконатися, що введений нуль не створював проблем нульових значень.
Белталовда

26

Ви можете використовувати цей код, щоб дозволити лише число в textField.

До цього встановіть делегата для textField

      textFieldName.delegate=self;

або

      [textFieldName setDelegate:self];

Потім використовуйте цей код, щоб дозволити лише text цифру в textField

      - (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
btw, для інших, хто використовує цей код, [string intValue]повертає 0 для @ "0" - тому if ([string intValue])не відповідає для @ "0". Краще використовуватиif ([string rangeOfCharacterFromSet:[[NSCharacterSet decimalDigitCharacterSet] invertedSet]].location != NSNotFound)
CharlesA

2
@".".intValueдорівнює 0. І @"0".intValueдорівнює також 0.
Jaybo

Щоб пояснити інші коментарі тут: Цей код не дозволяє користувачеві вводити нуль ( 0) символ.
Белталовда,

23

Спробуйте це, щоб уникнути проблем із очищенням текстового поля

Свіфт 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
}

Свіфт 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
Ви можете спростити метод делегування і просто залишилиreturn guard CharacterSet(charactersIn: "0123456789").isSuperset(of: CharacterSet(charactersIn: string))
hamsternik

Я скопіював і вставив у свій код і не працює. Як підключити його та змусити працювати?
Yash Jain

спочатку встановіть делегата textField (textField.delegate = self) і відповідайте протоколу UITextFieldDelegate.
SPatel

19

Дуже конкретні кроки для коду Swift

Ви можете надати логіку, яка обмежує введення текстового поля в func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Boolметод, реалізуючи UITextFieldDelegateпротокол.

Для наочності ці кроки передбачають, що ваша розкадровка містить файл контролер перегляду зоб’єктом текстового поля, який повинен приймати лише цифри.

  1. Створіть власний клас для контролера перегляду, який розширюється UIViewController. Переконайтеся, що сцена у вашій розкадровці посилається на власний клас, встановивши значення спеціального класу в інспекторі ідентифікації Xcode.

    import UIKit
    class YourCustomController: UIViewController {
        override func viewDidLoad() {        
            super.viewDidLoad()
        }
    }
    
  2. Створіть розетку з текстового поля вашої сцени на власний контролер перегляду.

    class YourCustomController: UIViewController {
        @IBOutlet weak var numberField: UITextField!
        ...
    }
    
  3. Застосуйте UITextFieldDelegateпротокол у власному контролері подання.

    class YourCustomController: UIViewController, UITextFieldDelegate {
        ...
    }
    
  4. У власному контролері подання viewDidLoad методі призначте делегата текстового поля своєму класу контролера користувацького перегляду.

    override func viewDidLoad() {        
        super.viewDidLoad()
        numberField.delegate = self
    }
    
  5. Додайте метод UITextFieldDelegate' func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool.

    Як результат того, що ваш власний контролер подання став numberFieldделегатом 'на попередньому кроці, цей метод буде викликатися кожного разу, коли користувач вводить символ у текстове поле. Якщо ваш метод повертаєтьсяtrue тоді символ залишиться в текстовому полі. Якщо ваш метод повернеться, falseто символ не залишиться в текстовому полі.

    stringПараметр символ , який вводиться користувачем. Якщо stringсимвол можна перетворити на an, Intтоді це від 0 до 9; в іншому випадку це якийсь нечисловий символ.

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

(Повний код контролера перегляду див. Нижче).


Приклад контролера подання з текстовим полем лише з цифрами

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

Приклад контролера подання з текстовим полем у десятковому вигляді

Якщо ви хочете підтримувати десяткове число, скористайтесь NSNumberFormatter. Дивіться коментарі до коду для відмінностей.

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

3
Це добре, але було зроблено невелике коригування, оскільки воно не дозволяє видалити що-небудь у полі без перевірки на наявність порожнього рядка. Я також додав можливість негативу, перевіривши перший символ if (рядок == "-" && range.location == 0) || string == "" {return true} повернути string.toInt ()! = nil
ickydime

return string.toInt() != nil Працював як оберіг. Дякую!
CalZone

Примітка в Swift 2 мені довелося змінити це наreturn Int(string) != nil
nevster

@nevster Дякую за коментар! Я думаю, що більшість розробників Swift перейшли або перейдуть до Swift 2 і вище. Тому я оновив відповідь, щоб відповідати перетворенню Swift 2 з рядка в int.
whyceewhite

7
Мені довелося внести ще одну зміну - клавіша видалення більше не працювала! Тож я змінив його наreturn 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
Це чудово працює для дробу, вам потрібно змінити правильний newString: NSString * newString = [textField.text stringByReplacingCharactersInRange: range withString: string];
Ідалі,

7

Я застосував це, і це працює !!

-(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
Щоб додати ".", Замініть if (character < 48) return NO; // 48 unichar for 0 if (character > 57) return NO; // 57 unichar for 9на " if ((character < 48 || character > 57) && character != 46)Я б додатково рекомендував порівняти characterз шістнадцятковими поданнями чисел, оскільки в цих випадках найчастіше використовуються шістнадцяткові числа. Тобтоif ((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

Свіфт:

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

1

стрімкий 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)
}

Тепер ви можете просто торкнутися лише 1234567890


як ти це реалізуєш? просто створення цієї функції не підключить її до UITextfield
Яш Джайн

0

Зберігайте різні дані презентації від внутрішнього представлення. Є простіший спосіб. Нехай NSNumberFormatterвиконує роботу:

 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

Якщо ви використовуєте мій шаблон специфікації, тоді код виглядає так

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
}

Як я можу обмежити UITextfield лише на отримання чисел і обмежити кількість чисел між 6 і 8?
Марко Альмейда

Привіт @MarcoAlmeida, поглянь на мій фреймворк SwiftyFORM, він може перевірити текст, github.com/neoneye/SwiftyFORM
neoneye

0

Я змінив відповідь @ iDev на роботу для цифр та ".":

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

стрімкий 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

Використовуйте цей код:

NSString* val = [[textField text] stringByReplacingCharactersInRange:range withString:string];
NSCharacterSet *allowedCharacterSet = [NSCharacterSet decimalDigitCharacterSet];
if ([[string componentsSeparatedByCharactersInSet:[allowedCharacterSet invertedSet]] count] > 1 || [val length] > 5) {
    return NO;
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.