2012-02-18 3 views
12

Najpierw ustawiam klawiaturę dla UITextField, aby użyć liczby w stylu dziesiętnym. Tak więc użytkownik może wprowadzać tylko cyfry i jedną cyfrę dziesiętną.Jak testować wprowadzanie znaków do UITextField, gdy użytkownik wprowadza znaki i zapobiega nieważnym znakom.

Co chcę zrobić, to przetestować dane wejściowe wprowadzane przez użytkownika i zapobiec wprowadzeniu wielu miejsc dziesiętnych i ograniczyć liczbę dziesiętną liczby do dwóch miejsc. Nie chcę zaokrąglać liczby ani nawet traktować danych wejściowych jako liczby. Po prostu chcę uniemożliwić użytkownikowi wpisanie więcej niż dwóch cyfr po prawej stronie miejsca dziesiętnego.

Odpowiedz

45

Rozwiązanie ostatecznie okazało się dość banalne. Niestety, wiele pytań i odpowiedzi związanych z tym pytaniem dotyczy sprawdzania poprawności lub formatowania wartości liczbowych, a nie jakimi użytkownik mógłby wprowadzić dane.

Następujące wdrożenie metody delegatów shouldChangeCharactersInRange jest moim rozwiązaniem. Jak zwykle, wyrazy regularne kołyszą się w tej sytuacji. RegExLib.com jest doskonałym źródłem przydatnych próbek lub rozwiązań RegEx. Nie jestem guru RegEx i zawsze staram się je trochę połączyć, więc wszelkie sugestie, aby to poprawić, są mile widziane.

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string 
{ 
    if (textField == self.quantityTextField) 
    { 
     NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string]; 

     NSString *expression = @"^([0-9]+)?(\\.([0-9]{1,2})?)?$"; 

     NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:expression 
                       options:NSRegularExpressionCaseInsensitive 
                       error:nil]; 
     NSUInteger numberOfMatches = [regex numberOfMatchesInString:newString 
                  options:0 
                   range:NSMakeRange(0, [newString length])];   
     if (numberOfMatches == 0) 
      return NO;   
    } 

    return YES; 
} 

Powyższy kod umożliwia użytkownikowi wprowadzenie tego rodzaju wartości: 1, 1.1, 1.11, .1, .11. Zauważ, że ta implementacja nie zastępuje łańcucha pola tekstowego, co spowodowałoby rekursję. To rozwiązanie po prostu odrzuca następny znak wprowadzany przez użytkownika, jeśli "newString" nie pasuje do wyrażenia regularnego.

+0

działa jak marzenie! – Breakpoint

+0

cześć! dzięki! twoja odpowiedź jest bardzo przydatna. Ale jak wyłączyć "." i ","?? – Frade

+1

Frade, chciałem, aby użytkownik mógł korzystać z ".". Powinieneś być w stanie ustawić parametr keyboardType of textField na UIKeyboardTypeNumberPad. Ta klawiatura nie zawiera interpunkcji. – Seamus

3

Standardowym sposobem radzenia sobie z tym problemem w systemie iOS jest podłączenie UITextFieldDelegate do urządzenia UITextField i wdrożenie metody textField:shouldChangeCharactersInRange:replacementString:. Wewnątrz tej metody możesz sprawdzić, czy ciąg znaków ma poprawny "kształt" dla twoich celów (jedna kropka, nie więcej niż dwie cyfry po kropce, itp.) I podać inny ciąg znaków, jeśli dane wejściowe nie są zgodne z oczekiwanym formatem.

-1

można przekazać ciąg uitexfield poniżej metody, powróci tak/no..accordingly można pokazać błąd

- (BOOL) validatePhone: (NSString *) aMobile { 
    NSString *phoneRegex = @"^+(?:[0-9] ?){6,14}[0-9]$"; 
    NSPredicate *phoneTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", phoneRegex]; 
    if (aMobile.length>0) { 
     NSString *mobileTextString = [[mobileText.text componentsSeparatedByCharactersInSet: 
             [[NSCharacterSet decimalDigitCharacterSet] invertedSet]] 
             componentsJoinedByString:@""]; 
     NSString *firstNumber = [aMobile substringToIndex:1]; 
     if (mobileTextString.length!=10){ 

      return NO; 
     } 

    } 
     return [phoneTest evaluateWithObject:aMobile]; 
} 
+0

Nie patrzyłem na to od dawna. Celem było uniemożliwienie użytkownikowi wprowadzania nieprawidłowych znaków. Po fakcie nie wykonuje sprawdzania poprawności. – Seamus

5

Good! Jeśli ktoś potrzebują pracy z non-US walutach: euro lub innych te z frakcją oddzielone przecinkiem zamiast kropki stosowania tego jednego:

NSString *expression = @"^([0-9]+)?([\\,\\.]([0-9]{1,2})?)?$"; 

Jedyną różnicą jest to, że pozwala on przecinka lub kropki. ([\, \.] - albo. albo,) Tylko sztuczka polega na tym, że musisz zastąpić przecinek kropką, gdy używasz swojego numeru, ponieważ komputer używa kropki do oddzielnego ułamka, a nie przecinka.

+0

Jak modyfikujesz powyższe wyrażenie regularne, aby zezwolić na znak minus na początku? Na przykład chciałbym zaakceptować liczby takie jak -100.50 – melsam

1

Po wielu eksperymentach i przyjrzeniu się innym rozwiązaniom (które wydają się zbyt skomplikowane i skrzypiące) wymyśliłem następujące, co uniemożliwia użytkownikowi wprowadzanie niczego oprócz prawidłowej kwoty waluty. Zasadniczo, niech wystąpienie NSNumberFormatter (utworzony w innym miejscu viewController) do ciężkiej pracy:

  • 1) Konwersja tekstu na numer (jeśli zero, to nie są nieprawidłowe znaki, więc nie zwraca)
  • 2), a następnie konwersję liczbę walut
  • 3), a następnie konwersję ciąg waluty powrotem do ilości i, jeśli inne niż w (czyli zbyt wiele miejsca dziesiętne wprowadzone) nie zwraca
  • 4), a następnie dokonać NSDecimalNumber, który jest czego chciałem. Oczywiście dla ciebie może być inaczej. Działa dla mnie jak dotąd - mam nadzieję, że to pomoże komuś.

Najpierw ustawiam klawiaturę na UIKeyboardTypeDecimalPad. Następnie użyłem następujący kod

-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string 

NSString *textString = [textField.text stringByReplacingCharactersInRange:range withString:string]; 

[numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle]; 
NSNumber *amountNumber = [numberFormatter numberFromString:textString]; 

if ([textString length] > 0) { 
    if (!amountNumber) { 
     return NO; 
    } 
} else { 
    amountNumber = @0; 
} 


[numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle]; 
NSString *amountStringer = [numberFormatter stringFromNumber:amountNumber]; 
NSNumber *amountAgain = [numberFormatter numberFromString:amountStringer]; 

// 
//make sure that the number obtained again is the same....prevents too many decimals.... 
if (![amountNumber isEqualToNumber:amountAgain]) { 
    return NO; 
} 

[numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle]; 
amountShow.text = amountStringer; 

self.amount = [NSDecimalNumber decimalNumberWithDecimal:[amountAgain decimalValue]]; 
NSLog(@"decimal Amount is %@", self.amount); 

return YES; 

}

0

Dla Swift 4 Głównym odpowiedź pytanie

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { 
    guard textField == quantityTextField, let textFieldString = textField.text as NSString? else { 
     return true 
    } 

    let newString = textFieldString.replacingCharacters(in: range, with: string) 
    let expression = "^([0-9]+)?(\\.([0-9]{1,2})?)?$" 

    let regex = try? NSRegularExpression(pattern: expression, options: .caseInsensitive) 
    let numberOfMathces = regex?.numberOfMatches(in: newString, options: NSRegularExpression.MatchingOptions(rawValue: 0), range: NSMakeRange(0, newString.characters.count)) 

    if numberOfMathces == 0 { 
     return false 
    } 

    return true 
} 
Powiązane problemy