Вопрос по ios – Как я могу ограничить количество десятичных знаков в UITextField?

27

У меня есть UITextField, который при нажатии вызывает цифровую панель с десятичной точкой в левом нижнем углу. Я пытаюсь ограничить поле, чтобы пользователь мог поставить только 1 десятичную отметку

например
2,5 ОК
2..5 НЕ ОК

Ваш Ответ

15   ответов
14

пример ограничивается только одной десятичной точкой и 2 десятичными. Вы можете настроить его под свои нужды.

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
    NSString *expression = @"^[0-9]*((\\.|,)[0-9]{0,2})?$";
    NSError *error = nil;
    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:expression options:NSRegularExpressionCaseInsensitive error:&error];
    NSUInteger numberOfMatches = [regex numberOfMatchesInString:newString options:0 range:NSMakeRange(0, [newString length])];
    return numberOfMatches != 0;
}
Это не работает.
Хороший ответ. Как конструктивный критик, я рекомендую вам улучшить свои знания в RegEx. Такие вещи, как & quot; ([0-9] +)? & Quot; может быть заменен на "[0-9] *" Это делает его более читабельным, а также более производительным. Я уже сделал правильные улучшения в ответ.
@ & Quot; ^ - [0-9] * ((\\ |,) [0-9] {0,2}.) $ & Quot?; за возможность ввода отрицательных чисел тоже.
1
Swift 4
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

    // Allow to remove character (Backspace)
    if string == "" {
        return true
    }

   // Block multiple dot
    if (textField.text?.contains("."))! && string == "." {
        return false
    }

    // Check here decimal places
    if (textField.text?.contains("."))! {
        let limitDecimalPlace = 2
        let decimalPlace = textField.text?.components(separatedBy: ".").last
        if (decimalPlace?.count)! < limitDecimalPlace {
            return true
        }
        else {
            return false
        }
    }
    return true
}
Objective-C
//Create this variable in .h file or .m file
float _numberOfDecimal;

//assign value in viewDidLoad method
numberOfDecimal = 2;

#pragma mark - TextFieldDelegate
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {

    // Allow to remove character (Backspace)
    if ([string isEqualToString:@""]) {
        return true;
    }

    // Block multiple dot
    if ([textField.text containsString:@"."] && [string isEqualToString:@"."]) {
        return false;
    }

    // Check here decimal places
    if ([textField.text containsString:@"."]) {
        NSString *strDecimalPlace = [[textField.text componentsSeparatedByString:@"."] lastObject];

        if (strDecimalPlace.length < _numberOfDecimal) {
            return true;
        }
        else {
            return false;
        }
    }
    return true;
}
4

Swift 3 Реализуйте этот метод UITextFieldDelegate, чтобы запретить пользователю вводить недопустимый номер:

 UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    let text = (textField.text ?? "") as NSString
    let newText = text.replacingCharacters(in: range, with: string)
    if let regex = try? NSRegularExpression(pattern: "^[0-9]*((\\.|,)[0-9]*)?$", options: .caseInsensitive) {
        return regex.numberOfMatches(in: newText, options: .reportProgress, range: NSRange(location: 0, length: (newText as NSString).length)) > 0
    }
    return false
}

Он работает с запятой или точкой в качестве десятичного разделителя. Вы также можете ограничить количество цифр дроби, используя этот шаблон:"^[0-9]*((\\.|,)[0-9]{0,2})?$" (в данном случае 2).

0
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    if([string isEqualToString:@"."]) {
        BOOL containsDecimal = [textField.text containsString:@"."];
        return !containsDecimal;
    }
    return YES;
}

иначе верните ДА.

0

которое дает вам контроль над количеством десятичных разрядов, так что пользователь может ввести только один десятичный разделитель, и вы также можете контролировать количество десятичных разрядов.

Просто установитеdecimalPlacesLimit ценить правильно.

Смотрите метод:

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    NSLog(@"text on the way: %@", string);
    NSUInteger decimalPlacesLimit = 2;

    NSRange rangeDot = [textField.text rangeOfString:@"." options:NSCaseInsensitiveSearch];
    NSRange rangeComma = [textField.text rangeOfString:@"," options:NSCaseInsensitiveSearch];
    if (rangeDot.length > 0 || rangeComma.length > 0){
        if([string isEqualToString:@"."]) {
            NSLog(@"textField already contains a separator");
            return NO;
        } else {
            NSArray *explodedString = [textField.text componentsSeparatedByString:@"."];
            NSString *decimalPart = explodedString[1];
            if (decimalPart.length >= decimalPlacesLimit && ![string isEqualToString:@""]) {
                NSLog(@"textField already contains %d decimal places", decimalPlacesLimit);
                return NO;
            }
        }
    }

    return YES;
}
1

Swift 3

Не нужно создавать массив и проверять счетчик. Пользователь с ограничением может разместить только одну десятичную отметку, как это.

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    if (textField.text?.contains("."))! && string.contains(".")
    {
        return false
    }
    else
    {
        return true
    }
}
0

Swift 4

Эффективный и простой способ избежать нескольких десятичных знаков (. Или,) в UITextField:

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    if(string == "," || string == "." ){

        if ((textField.text?.contains(","))! || (textField.text?.contains("."))!){
            return false
        }
    }
    return true
}
5

следующий подход проверяет три случая, которые полезны при работе с денежными форматами:

Extremely large amounts More than 2 characters after the decimal point More than 1 decimal points

Убедитесь, что делегат вашего текстового поля установлен правильно, ваш класс соответствуетUITextField протокол и добавьте следующий метод делегата.

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
  // Check for deletion of the $ sign
  if (range.location == 0 && [textField.text hasPrefix:@"$"])
    return NO;

  NSString *updatedText = [textField.text stringByReplacingCharactersInRange:range withString:string];
  NSArray *stringsArray = [updatedText componentsSeparatedByString:@"."];

  // Check for an absurdly large amount
  if (stringsArray.count > 0)
  {
    NSString *dollarAmount = stringsArray[0];
    if (dollarAmount.length > 6)
      return NO;
  }

  // Check for more than 2 chars after the decimal point
  if (stringsArray.count > 1)
  {
    NS,String *centAmount = stringsArray[1];
    if (centAmount.length > 2)
      return NO;
  }

  // Check for a second decimal point
  if (stringsArray.count > 2)
    return NO;

  return YES;
}
Есть дело, которое обрабатывается неправильно: если вы набрали 6 символов в долларовой сумме, вы можете в любом случае ввести centAmount.
0

максимальное количество целых чисел равно 4, то есть 9999, а максимальное количество десятичных цифр равно 2. Таким образом, максимальное число может быть 9999,99

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


    // 100 is the tag value of our textfield
    /*or you may use "if textfield == myTextField{" if you have an IBOutlet to that textfield */
    if textField.tag == 100 {

        //max length limit of text is 8
        if textField.text!.count > 8 && string != "" {
            return false
        }

        let maxLength = 8
        let currentString: NSString = textField.text! as NSString 

// Использовать следующий код Если вы вводите цену в это текстовое поле и хотите, чтобы $ автоматически вставлялось при запуске, когда пользователь начинает печатать в этом текстовом поле, или вы можете поместить другой символ в начале вместо $. В противном случае прокомментируйте следующие 3 строки кода условия if

        if currentString.length == 0 {
            priceTextField.text = "$"
        }

// новая строка после вставки новых введенных символов

        let newString: NSString =
            currentString.replacingCharacters(in: range, with: string) as NSString


        if newString.length > maxLength{
            return false
        }

        if (textField.text!.range(of: ".") != nil) {
            let numStr = newString.components(separatedBy: ".")
            if numStr.count>1{
                let decStr = numStr[1]
                if decStr.length > 2{
                    return false
                }
            }
        }

        var priceStr: String = newString as String

        if (textField.text!.range(of: "$") != nil) {
            priceStr = priceStr.replacingOccurrences(of: "$", with: "")
        }

        let price: Double = Double(priceStr) ?? 0

        if price > 9999.99{
            return false
        }

        switch string {
        case "0","1","2","3","4","5","6","7","8","9":
            return true
        case ".":
            let array = Array(textField.text!)
            var decimalCount = 0
            for character in array {
                if character == "." {
                    decimalCount = decimalCount + 1
                }
            }

            if decimalCount == 1 {
                return false
            } else {
                return true
            }
        default:

            let array = Array(string)
            if array.count == 0 {
                return true
            }
            return false
        }
    }
    return true
}
0

[NSString stringWithFormat:@"%9.5f", x]; Где 5 - десятичное число после ",".

2

public func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {

    if(text == "," || text == "." ){
        let countdots = textView.text!.componentsSeparatedByString(".").count - 1

        if countdots > 0 && (text == "." || text == "," )
        {
            return false
        }
    }

    return true
}
text может содержать несколько символов, так что вы не можете проверить это так.
42

// Only allow one decimal point
// Example assumes ARC - Implement proper memory management if not using.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string 
{
    NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
    NSArray  *arrayOfString = [newString componentsSeparatedByString:@"."];

    if ([arrayOfString count] > 2 ) 
        return NO;

    return YES;
}

Это создает массив строк, разделенных десятичной точкой, поэтому, если существует более одной десятичной точки, у нас будет как минимум 3 элемента в массиве.

Правда! Есть много способов сделать это. Я обычно использую это, потому что часто я хочу сделать что-то другое с целой и десятичной частью.
@nizx Для этого конкретного случая я не думаю, что это действительно имеет большое значение, хотя ваш пример длиннее и "выглядит" сложнее для нового пользователя. Для более сложных примеров вы вполне можете быть правы, или если они являются числами, тогда может быть целесообразно использовать NSNumberFormatter.
Вместо @ & quot;. & Quot; для десятичного разделителя можно также получить его из [[NSLocale currentLocale] objectForKey: NSLocaleDecimalSeparator]]. Таким образом, код также будет работать правильно для регионов, использующих запятую в качестве разделителя.
Использование регулярного выражения дает вам лучший контроль над символами, которые принимает текстовое поле, и форматом, который они принимают.
Вместо использования componentSeparatedByString можно использовать выражение NSRegularExpression, чтобы определить, содержит ли newString более одного десятичного знака.
0

для которого вы устанавливаете делегат UITextField, добавьте метод, который отвечает& Quot;[- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string]".

Тогда вы можете использоватьNSNumberFormatter объект или вы можете проверить грубую силу уже существующего знака после запятой (возвращаяNO если десятичный знак уже существует).

2
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string 
{
    if(textField == min_textfield )
    {
        if([textField.text rangeOfString:@"."].location == NSNotFound)
        {
            if([string isEqualToString:@"."] )
            {
                flag_for_text = 1;
            }
            else 
            {
                textField.text = [NSMutableString stringWithFormat:@"%@",textField.text];
            }
        }
        else 
        {
            if([string isEqualToString:@"."])
            {
                return NO;
            }
            else 
            {
                textField.text = [NSMutableString stringWithFormat:@"%@",textField.text];
            }
        }
    }
}
6

For Swift 2.3 to prevent user for enter decimal number after two places -

 UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool
{
    let decimalPlacesLimit = 2
    let rangeDot = txtPrice.text!.rangeOfString(".", options: .CaseInsensitiveSearch)

    if rangeDot?.count > 0
    {
        if (string == ".")
        {
            print("textField already contains a separator")
            return false
        }
        else {

            var explodedString = txtPrice.text!.componentsSeparatedByString(".")
            let decimalPart = explodedString[1]
            if decimalPart.characters.count >= decimalPlacesLimit && !(string == "")
            {
                print("textField already contains \(decimalPlacesLimit) decimal places")
                return false
            }
        }
    }
}
Добро пожаловать в переполнение стека! Хотя вы, возможно, решили проблему этого пользователя, ответы только на код не очень полезны для пользователей, которые придут к этому вопросу в будущем. Пожалуйста, измените ваш ответ, чтобы объяснить, почему ваш код решает исходную проблему.

Похожие вопросы