Bir dize girdisini nasıl doğrularım UITextField
? Dizenin ondalık basamaklar dahil sayısal olup olmadığını kontrol etmek istiyorum.
Yanıtlar:
Bu kodu Mac uygulamamda kullanıyorum, aynı veya benzerinin iPhone ile çalışması gerekir. RegexKitLite normal ifadelerine dayanır ve geçersiz olduğunda metni kırmızıya çevirir.
static bool TextIsValidValue( NSString* newText, double &value )
{
bool result = false;
if ( [newText isMatchedByRegex:@"^(?:|0|[1-9]\\d*)(?:\\.\\d*)?$"] ) {
result = true;
value = [newText doubleValue];
}
return result;
}
- (IBAction) doTextChanged:(id)sender;
{
double value;
if ( TextIsValidValue( [i_pause stringValue], value ) ) {
[i_pause setTextColor:[NSColor blackColor]];
// do something with the value
} else {
[i_pause setTextColor:[NSColor redColor]];
}
}
(?:|0|[1-9]\\d*)(?:\\.\\d*)
ne anlama geldiğini görmek için kopyalayıp yapıştırın . Ayrıca bkz. Regex Wikipedia
Bunu aşağıdaki gibi birkaç satırda yapabilirsiniz:
BOOL valid;
NSCharacterSet *alphaNums = [NSCharacterSet decimalDigitCharacterSet];
NSCharacterSet *inStringSet = [NSCharacterSet characterSetWithCharactersInString:myInputField.text];
valid = [alphaNums isSupersetOfSet:inStringSet];
if (!valid) // Not numeric
- bu, girişin yalnızca sayısal karakter olduğunu doğrulamak içindir. NSCharacterSet
Diğer seçenekler için belgelere bakın . Herhangi bir geçerli girdi karakteri kümesini belirtmek için characterSetWithCharactersInString'i kullanabilirsiniz.
Bunu yapmanın birkaç yolu var:
nil
.IMO, böyle bir şey kullanmak -[NSString doubleValue]
en iyi seçenek olmayacaktır çünkü her ikisi de @"0.0"
ve @"abc"
doubleValue 0 olacaktır. * Değer yöntemlerinin tümü, dizeyi düzgün bir şekilde dönüştüremiyorlarsa 0 döndürür, bu nedenle, meşru dizge @"0"
ve geçersiz dizge. C'nin strtol
işlevi gibi bir şey aynı sorunu yaşayacaktır.
Bence NSNumberFormatter kullanmanın en iyi seçenek olacağını düşünüyorum, çünkü yerel ayarı hesaba katıyor (yani, @"1,23"
Avrupa'daki sayı @"1.23"
, ABD'deki sayı ).
NSNumberFormatter * f = [[NSNumberFormatter alloc] init]; NSNumber * n = [f numberFromString:@"34jfkjdskj80"]; NSLog(@"N: %@", n);
NSScanner
benzeri olması gerektiğini düşündüm (örneğin, ). NSNumberFormatter
setLocale:
[NSLocale currentLocale]
Bir kullanıcının yalnızca sayı girmesine izin verilmesini istiyorsanız, ViewController'ınızın UITextFieldDelegate'in bir parçasını uygulamasını sağlayabilir ve bu yöntemi tanımlayabilirsiniz:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSString *resultingString = [textField.text stringByReplacingCharactersInRange: range withString: string];
// The user deleting all input is perfectly acceptable.
if ([resultingString length] == 0) {
return true;
}
NSInteger holder;
NSScanner *scan = [NSScanner scannerWithString: resultingString];
return [scan scanInteger: &holder] && [scan isAtEnd];
}
Muhtemelen daha verimli yollar vardır, ancak bunu oldukça uygun bir yol buluyorum . Ve yöntem, çiftleri veya her neyse, doğrulamaya kolayca uyarlanabilir olmalıdır: sadece scanDouble: veya benzerini kullanın.
#pragma mark - UItextfield Delegate
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
if ([string isEqualToString:@"("]||[string isEqualToString:@")"]) {
return TRUE;
}
NSLog(@"Range ==%d ,%d",range.length,range.location);
//NSRange *CURRANGE = [NSString rangeOfString:string];
if (range.location == 0 && range.length == 0) {
if ([string isEqualToString:@"+"]) {
return TRUE;
}
}
return [self isNumeric:string];
}
-(BOOL)isNumeric:(NSString*)inputString{
BOOL isValid = NO;
NSCharacterSet *alphaNumbersSet = [NSCharacterSet decimalDigitCharacterSet];
NSCharacterSet *stringSet = [NSCharacterSet characterSetWithCharactersInString:inputString];
isValid = [alphaNumbersSet isSupersetOfSet:stringSet];
return isValid;
}
Peter Lewis'in yukarıdaki cevabını ( UITextField girişinin yalnızca sayısal olduğunu kontrol edin ) NSPredicates ile birleştiren birkaç tek satırlık yazıyı burada bulabilirsiniz.
#define REGEX_FOR_NUMBERS @"^([+-]?)(?:|0|[1-9]\\d*)(?:\\.\\d*)?$"
#define REGEX_FOR_INTEGERS @"^([+-]?)(?:|0|[1-9]\\d*)?$"
#define IS_A_NUMBER(string) [[NSPredicate predicateWithFormat:@"SELF MATCHES %@", REGEX_FOR_NUMBERS] evaluateWithObject:string]
#define IS_AN_INTEGER(string) [[NSPredicate predicateWithFormat:@"SELF MATCHES %@", REGEX_FOR_INTEGERS] evaluateWithObject:string]
Tam sayı testi için şunlar olacaktır:
- (BOOL) isIntegerNumber: (NSString*)input
{
return [input integerValue] != 0 || [input isEqualToString:@"0"];
}
Dizenizin doubleValue'unu şu şekilde kullanabilirsiniz:
NSString *string=@"1.22";
double a=[string doubleValue];
Sanırım dizge geçersizse bu 0.0 olarak geri dönecektir (bir istisna atabilir, bu durumda onu yakalayabilirsiniz, dokümanlar 0.0 tho der). daha fazla bilgi burada
Merhaba aynı problemi yaşadım ve kullandığım cevabı göremiyorum, işte burada.
Metin alanımı IB aracılığıyla oluşturdum ve bağladım. Kontrol + Sürükle ile koduma bağladığımda, Eylemi seçtim, ardından Değiştirilenleri Düzenleme olayını seçtim. Bu, her karakter girişindeki yöntemi tetikler. Uygun olması için farklı bir etkinlik kullanabilirsiniz.
Daha sonra metni değiştirmek için bu basit kodu kullandım. Ondalık / nokta karakterini ve sayılarını içerecek şekilde kendi karakter setimi oluşturduğuma dikkat edin. Temel olarak geçersiz karakterlerin üzerindeki dizeyi ayırır, ardından boş dizelerle yeniden birleştirir.
- (IBAction)myTextFieldEditingChangedMethod:(UITextField *)sender {
NSCharacterSet *validCharacterSet = [NSCharacterSet characterSetWithCharactersInString:@".0123456789"];
NSCharacterSet *invalidCharacterSet = validCharacterSet.invertedSet;
sender.text = [[sender.text componentsSeparatedByCharactersInSet:invalidCharacterSet] componentsJoinedByString:@""];
}
Krediler: NSString'den sayılar dışındaki tüm sayıları kaldırın
Oyuna geç kaldım ama burada kullanışlı küçük bir kategori kullanıyorum, bu ondalık basamakları ve bunun için kullanılan yerel sembolü açıklıyor. özüne buradan ulaşabilirsiniz
@interface NSString (Extension)
- (BOOL) isAnEmail;
- (BOOL) isNumeric;
@end
@implementation NSString (Extension)
/**
* Determines if the current string is a valid email address.
*
* @return BOOL - True if the string is a valid email address.
*/
- (BOOL) isAnEmail
{
NSString *emailRegex = @"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}";
NSPredicate *emailTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", emailRegex];
return [emailTest evaluateWithObject:self];
}
/**
* Determines if the current NSString is numeric or not. It also accounts for the localised (Germany for example use "," instead of ".") decimal point and includes these as a valid number.
*
* @return BOOL - True if the string is numeric.
*/
- (BOOL) isNumeric
{
NSString *localDecimalSymbol = [[NSLocale currentLocale] objectForKey:NSLocaleDecimalSeparator];
NSMutableCharacterSet *decimalCharacterSet = [NSMutableCharacterSet characterSetWithCharactersInString:localDecimalSymbol];
[decimalCharacterSet formUnionWithCharacterSet:[NSCharacterSet alphanumericCharacterSet]];
NSCharacterSet* nonNumbers = [decimalCharacterSet invertedSet];
NSRange r = [self rangeOfCharacterFromSet: nonNumbers];
if (r.location == NSNotFound)
{
// check to see how many times the decimal symbol appears in the string. It should only appear once for the number to be numeric.
int numberOfOccurances = [[self componentsSeparatedByString:localDecimalSymbol] count]-1;
return (numberOfOccurances > 1) ? NO : YES;
}
else return NO;
}
@end
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if(string.length > 0)
{
NSCharacterSet *numbersOnly = [NSCharacterSet characterSetWithCharactersInString:@"0123456789"];
NSCharacterSet *characterSetFromTextField = [NSCharacterSet characterSetWithCharactersInString:string];
BOOL stringIsValid = [numbersOnly isSupersetOfSet:characterSetFromTextField];
return stringIsValid;
}
return YES;
}
IMO, hedefinize ulaşmanın en iyi yolu, normal klavye yerine sayısal bir klavye görüntülemektir. Bu, kullanıcının hangi anahtarları kullanabileceğini kısıtlar. Bu, doğrulama yapma ihtiyacını azaltır ve daha da önemlisi kullanıcının hata yapmasını engeller. Sayısal tuş takımı, sayıları girmek için çok daha hoş çünkü tuşlar çok daha büyük.
Arayüz oluşturucuda UITextField'ı seçin, Nitelikler Denetçisine gidin ve "Klavye Türü" nü "Ondalık Ped" olarak değiştirin.
Bu, klavyenin şöyle görünmesini sağlar:
Yapılması gereken tek şey, kullanıcının iki ondalık basamak girmemesini sağlamaktır. Bunu düzenleme sırasında yapabilirsiniz. Aşağıdaki kodu görünüm denetleyicinize ekleyin. Bu kod, girildiği anda ikinci bir ondalık basamağı kaldırır. Kullanıcıya sanki 2. ondalık ilk etapta hiç görünmemiş gibi görünür.
- (void)viewDidLoad
{
[super viewDidLoad];
[self.textField addTarget:self
action:@selector(textFieldDidChange:)
forControlEvents:UIControlEventEditingChanged];
}
- (void)textFieldDidChange:(UITextField *)textField
{
NSString *text = textField.text;
NSRange range = [text rangeOfString:@"."];
if (range.location != NSNotFound &&
[text hasSuffix:@"."] &&
range.location != (text.length - 1))
{
// There's more than one decimal
textField.text = [text substringToIndex:text.length - 1];
}
}
@property (strong) NSNumberFormatter *numberFormatter;
@property (strong) NSString *oldStringValue;
- (void)awakeFromNib
{
[super awakeFromNib];
self.numberFormatter = [[NSNumberFormatter alloc] init];
self.oldStringValue = self.stringValue;
[self setDelegate:self];
}
- (void)controlTextDidChange:(NSNotification *)obj
{
NSNumber *number = [self.numberFormatter numberFromString:self.stringValue];
if (number) {
self.oldStringValue = self.stringValue;
} else {
self.stringValue = self.oldStringValue;
}
}
Eski iş parçacığı, ancak Apple'ın NSRegularExpression
iOS 4.0'da tanıtıldığından bahsetmeye değer . (Normal ifadeyi Peter'ın cevabından alır)
// Look for 0-n digits from start to finish
NSRegularExpression *noFunnyStuff = [NSRegularExpression regularExpressionWithPattern:@"^(?:|0|[1-9]\\d*)(?:\\.\\d*)?$" options:0 error:nil];
// There should be just one match
if ([noFunnyStuff numberOfMatchesInString:<#theString#> options:0 range:NSMakeRange(0, <#theString#>.length)] == 1)
{
// Yay, digits!
}
NSRegularExpression
Örneği bir yerde saklamanızı öneririm .
Yalnızca tam sayılara izin veren bir metin alanı istedim. İşte bulduğum sonuç (buradan ve başka yerlerden gelen bilgileri kullanarak):
Tamsayı sayı biçimlendiricisi oluşturun (yeniden kullanılabilmesi için UIApplicationDelegate'de):
@property (nonatomic, retain) NSNumberFormatter *integerNumberFormatter;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Create and configure an NSNumberFormatter for integers
integerNumberFormatter = [[NSNumberFormatter alloc] init];
[integerNumberFormatter setMaximumFractionDigits:0];
return YES;
}
UITextFieldDelegate'te filtre kullanın:
@interface MyTableViewController : UITableViewController <UITextFieldDelegate> {
ictAppDelegate *appDelegate;
}
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
// Make sure the proposed string is a number
NSNumberFormatter *inf = [appDelegate integerNumberFormatter];
NSString* proposedString = [textField.text stringByReplacingCharactersInRange:range withString:string];
NSNumber *proposedNumber = [inf numberFromString:proposedString];
if (proposedNumber) {
// Make sure the proposed number is an integer
NSString *integerString = [inf stringFromNumber:proposedNumber];
if ([integerString isEqualToString:proposedString]) {
// proposed string is an integer
return YES;
}
}
// Warn the user we're rejecting the change
AudioServicesPlayAlertSound(kSystemSoundID_Vibrate);
return NO;
}
Swift 3'te iPad ve iPhone ile çalışan tek (.) Noktalı metin alanlarındaki ondalık değerleri kabul edin
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let inverseSet = NSCharacterSet(charactersIn:"0123456789").inverted
let components = string.components(separatedBy: inverseSet)
let filtered = components.joined(separator: "")
if filtered == string {
return true
} else {
if string == "." {
let countdots = textField.text!.components(separatedBy:".").count - 1
if countdots == 0 {
return true
}else{
if countdots > 0 && string == "." {
return false
} else {
return true
}
}
}else{
return false
}
}
}
Daha uluslararası olmak için (ve yalnızca ABD renkli değil ;-)) yukarıdaki kodu şununla değiştirin:
-(NSNumber *) getNumber
{
NSString* localeIdentifier = [[NSLocale autoupdatingCurrentLocale] localeIdentifier];
NSLocale *l_en = [[NSLocale alloc] initWithLocaleIdentifier: localeIdentifier] ;
return [self getNumberWithLocale: [l_en autorelease] ];
}
Bu cevap, daha önce söylendiği gibi NSFormatter'ı kullanır. Bunu kontrol et:
@interface NSString (NSNumber)
- (BOOL) isNumberWithLocale:(NSLocale *) stringLocale;
- (BOOL) isNumber;
- (NSNumber *) getNumber;
- (NSNumber *) getNumberWithLocale:(NSLocale*) stringLocale;
@end
@implementation NSString (NSNumber)
- (BOOL) isNumberWithLocale:(NSLocale *) stringLocale
{
return [self getNumberWithLocale:stringLocale] != nil;
}
- (BOOL) isNumber
{
return [ self getNumber ] != nil;
}
- (NSNumber *) getNumber
{
NSLocale *l_en = [[NSLocale alloc] initWithLocaleIdentifier: @"en_US"] ;
return [self getNumberWithLocale: [l_en autorelease] ];
}
- (NSNumber *) getNumberWithLocale:(NSLocale*) stringLocale
{
NSNumberFormatter *formatter = [[ [ NSNumberFormatter alloc ] init ] autorelease];
[formatter setLocale: stringLocale ];
return [ formatter numberFromString:self ];
}
@end
Umarım birine yardımcı olur. =)
#import "NSString+Extension.h"
//@interface NSString (Extension)
//
//- (BOOL) isAnEmail;
//- (BOOL) isNumeric;
//
//@end
@implementation NSString (Extension)
- (BOOL) isNumeric
{
NSString *emailRegex = @"[0-9]+";
NSPredicate *emailTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", emailRegex];
return [emailTest evaluateWithObject:self];
// NSString *localDecimalSymbol = [[NSLocale currentLocale] objectForKey:NSLocaleDecimalSeparator];
// NSMutableCharacterSet *decimalCharacterSet = [NSMutableCharacterSet characterSetWithCharactersInString:localDecimalSymbol];
// [decimalCharacterSet formUnionWithCharacterSet:[NSCharacterSet alphanumericCharacterSet]];
//
// NSCharacterSet* nonNumbers = [decimalCharacterSet invertedSet];
// NSRange r = [self rangeOfCharacterFromSet: nonNumbers];
//
// if (r.location == NSNotFound)
// {
// // check to see how many times the decimal symbol appears in the string. It should only appear once for the number to be numeric.
// int numberOfOccurances = [[self componentsSeparatedByString:localDecimalSymbol] count]-1;
// return (numberOfOccurances > 1) ? NO : YES;
// }
// else return NO;
}
Swift 4'te:
let formatString = "12345"
if let number = Decimal(string:formatString){
print("String contains only number")
}
else{
print("String doesn't contains only number")
}
Bu, şunları kapsar: Ondalık bölüm kontrolü (izin verilen ondalık sayılar dahil), kopyala / yapıştır kontrolü, uluslararası ayırıcılar.
Adımlar:
Görünüm denetleyicinizin UITextFieldDelegate'ten miras aldığından emin olun
class MyViewController: UIViewController, UITextFieldDelegate {...
ViewDidLoad'da, kontrol temsilcinizi self olarak ayarlayın:
func viewDidLoad () {super.viewDidLoad (); yourTextField.delegate = self}
Aşağıdaki yöntemi uygulayın ve "decsAllowed" sabitini istenen miktarda ondalık sayı veya doğal bir sayı istiyorsanız 0 ile güncelleyin.
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let decsAllowed: Int = 2
let candidateText = NSString(string: textField.text!).replacingCharacters(in: range, with: string)
let decSeparator: String = NumberFormatter().decimalSeparator!;
let splitted = candidateText.components(separatedBy: decSeparator)
let decSeparatorsFound = splitted.count - 1
let decimalPart = decSeparatorsFound > 0 ? splitted.last! : ""
let decimalPartCount = decimalPart.characters.count
let characterSet = NSMutableCharacterSet.decimalDigit()
if decsAllowed > 0 {characterSet.addCharacters(in: decSeparator)}
let valid = characterSet.isSuperset(of: CharacterSet(charactersIn: candidateText)) &&
decSeparatorsFound <= 1 &&
decsAllowed >= decimalPartCount
return valid
}
Daha sonra bu dizeyi güvenli bir şekilde bir sayıya dönüştürmeniz gerekirse, Double (yourstring) veya Int (yourstring) tipi cast veya daha akademik bir yol kullanabilirsiniz:
let formatter = NumberFormatter()
let theNumber: NSNumber = formatter.number(from: yourTextField.text)!
+ (BOOL) TextIsValidValue:(NSString*)newText:(double)&value:
...