У меня есть 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;
}