У меня есть UITextField, который при нажатии вызывает цифровую панель с десятичной точкой в левом нижнем углу. Я пытаюсь ограничить поле так, чтобы пользователь мог разместить только 1 десятичную метку
например.
2.5 OK
2..5 НЕ ОК
У меня есть UITextField, который при нажатии вызывает цифровую панель с десятичной точкой в левом нижнем углу. Я пытаюсь ограничить поле так, чтобы пользователь мог разместить только 1 десятичную метку
например.
2.5 OK
2..5 НЕ ОК
Реализовать метод shouldChangeCharactersInRange следующим образом:
// 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 элемента в массиве.
Вот пример с регулярным выражением, пример ограничивает только одну десятичную точку и 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;
}
Основываясь на принятом ответе, следующий подход проверяет три случая, которые полезны при работе с денежными форматами:
Убедитесь, что делегат текстового поля установлен правильно, ваш класс соответствует протоколу 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)
{
NSString *centAmount = stringsArray[1];
if (centAmount.length > 2)
return NO;
}
// Check for a second decimal point
if (stringsArray.count > 2)
return NO;
return YES;
}
Для Swift 2.3, чтобы пользователь не вводил десятичное число после двух мест -
func textField(textField: 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
}
}
}
}
-(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];
}
}
}
}
Попробуйте следующее: -
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
}
Swift 3
Не нужно создавать массив и проверять количество. Ограниченный пользователь может разместить только 1 десятичную метку.
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if (textField.text?.contains("."))! && string.contains(".")
{
return false
}
else
{
return true
}
}
Swift 3 Внедрите этот метод UITextFieldDelegate, чтобы пользователь не вводил неверный номер:
func textField(_ textField: 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).
В любом объекте, в который вы установите делегат UITextField, добавьте метод, который отвечает на "[- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string]" .
Затем вы можете либо использовать объект NSNumberFormatter, либо выполнить проверку грубой силы для уже существующей метки десятичного знака (возврат NO, если десятичная метка уже существует).
Кратко сказано, формат числа выглядит следующим образом [NSString stringWithFormat:@"%9.5f", x]; Где 5 - десятичное после ",".
Я сделал решение, которое позволяет вам контролировать количество десятичных знаков, поэтому пользователь может набирать только один разделитель на десятичные знаки, и вы также можете контролировать количество десятичных знаков.
Просто установите значение 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;
}