如何验证输入到 a 的字符串UITextField
?我想检查字符串是否为数字,包括小数点。
22 回答
您可以像这样用几行代码来完成:
BOOL valid;
NSCharacterSet *alphaNums = [NSCharacterSet decimalDigitCharacterSet];
NSCharacterSet *inStringSet = [NSCharacterSet characterSetWithCharactersInString:myInputField.text];
valid = [alphaNums isSupersetOfSet:inStringSet];
if (!valid) // Not numeric
-- 这是为了验证输入是否仅为数字字符。查看NSCharacterSet
其他选项的文档。您可以使用 characterSetWithCharactersInString 来指定任何一组有效的输入字符。
有几种方法可以做到这一点:
- 使用 NSNumberFormatter 的 numberFromString: 方法。如果它可以正确解析字符串,或者不能正确解析,这将返回一个 NSNumber
nil
。 - 使用 NSScanner
- 剥离任何非数字字符并查看字符串是否仍然匹配
- 使用正则表达式
IMO,使用类似的东西-[NSString doubleValue]
不是最好的选择,因为两者@"0.0"
的@"abc"
doubleValue 都为 0。如果 *value 方法无法正确转换字符串,则它们都返回 0,因此很难区分的合法字符串@"0"
和无效字符串。像 C 的strtol
函数这样的东西也会有同样的问题。
我认为使用 NSNumberFormatter 将是最好的选择,因为它考虑了语言环境(即@"1,23"
欧洲的数字,而不是@"1.23"
美国的数字)。
我在我的 Mac 应用程序中使用此代码,相同或相似的代码应该适用于 iPhone。它基于 RegexKitLite 正则表达式,并在其无效时将文本变为红色。
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]];
}
}
如果你希望用户只被允许输入数字,你可以让你的 ViewController 实现 UITextFieldDelegate 的一部分并定义这个方法:
- (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];
}
可能有更有效的方法,但我发现这是一种非常方便的方法。并且该方法应该很容易适应验证双打或其他:只需使用 scanDouble: 或类似的。
#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 上面的答案(检查 UITextField 的输入是否仅为数字)与 NSPredicates 结合起来的单行代码
#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]
对于整数测试,它将是:
- (BOOL) isIntegerNumber: (NSString*)input
{
return [input integerValue] != 0 || [input isEqualToString:@"0"];
}
您可以使用字符串的 doubleValue ,例如
NSString *string=@"1.22";
double a=[string doubleValue];
我认为如果字符串无效,这将返回 a 作为 0.0(它可能会引发异常,在这种情况下你可以抓住它,文档说 0.0 tho)。更多信息在这里
嗨有完全相同的问题,我没有看到我发布的答案,所以在这里。
我通过 IB 创建并连接了我的文本字段。当我通过 Control+Drag 将它连接到我的代码时,我选择了 Action,然后选择了 Editing Changed 事件。这会在每个字符条目上触发该方法。您可以使用不同的事件来适应。
之后,我使用这个简单的代码来替换文本。请注意,我创建了自己的字符集以包含小数/句点字符和数字。基本上将无效字符上的字符串分开,然后用空字符串重新加入它们。
- (IBAction)myTextFieldEditingChangedMethod:(UITextField *)sender {
NSCharacterSet *validCharacterSet = [NSCharacterSet characterSetWithCharactersInString:@".0123456789"];
NSCharacterSet *invalidCharacterSet = validCharacterSet.invertedSet;
sender.text = [[sender.text componentsSeparatedByCharactersInSet:invalidCharacterSet] componentsJoinedByString:@""];
}
游戏迟到了,但我在这里使用了一个方便的小类别,它说明了小数位和用于它的本地符号。链接到这里的要点
@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 实现目标的最佳方法是显示数字键盘而不是普通键盘。这限制了用户可以使用哪些密钥。这减轻了进行验证的需要,更重要的是它可以防止用户犯错误。数字键盘也更适合输入数字,因为键要大得多。
在界面生成器中选择 UITextField,转到属性检查器并将“键盘类型”更改为“小数点”。
这将使键盘看起来像这样:
剩下要做的唯一事情是确保用户不输入两位小数。您可以在他们编辑时执行此操作。将以下代码添加到您的视图控制器。此代码在输入后立即删除第二个小数位。在用户看来,就好像第 2 位小数从来没有出现过一样。
- (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;
}
}
老线程,但值得一提的是苹果NSRegularExpression
在 iOS 4.0 中引入。(从彼得的回应中取正则表达式)
// 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
实例存储在某处。
我想要一个只允许整数的文本字段。这是我最终得到的结果(使用来自这里和其他地方的信息):
创建整数格式化程序(在 UIApplicationDelegate 中以便可以重用):
@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 中使用过滤器:
@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;
}
不是那么优雅,但简单:)
- (BOOL) isNumber: (NSString*)input
{
return [input doubleValue] != 0 || [input isEqualToString:@"0"] || [input isEqualToString:@"0.0"];
}
在 Swift 3 中使用 iPad 和 iPhone 接受带有单个 (.) 点的文本字段中的十进制值
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
}
}
}
如前所述,此答案使用 NSFormatter 。看看这个:
@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
我希望它可以帮助某人。=)
为了更加国际化(不仅仅是美国色;-))只需在上面的代码中替换为
-(NSNumber *) getNumber
{
NSString* localeIdentifier = [[NSLocale autoupdatingCurrentLocale] localeIdentifier];
NSLocale *l_en = [[NSLocale alloc] initWithLocaleIdentifier: localeIdentifier] ;
return [self getNumberWithLocale: [l_en autorelease] ];
}
#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 中:
let formatString = "12345"
if let number = Decimal(string:formatString){
print("String contains only number")
}
else{
print("String doesn't contains only number")
}
这包括:小数部分控制(包括允许的小数位数)、复制/粘贴控制、国际分隔符。
脚步:
确保您的视图控制器继承自 UITextFieldDelegate
类 MyViewController: UIViewController, UITextFieldDelegate {...
在 viewDidLoad 中,将您的控制委托设置为 self:
覆盖 func viewDidLoad() { super.viewDidLoad(); yourTextField.delegate = self }
实现以下方法并使用所需的小数位数更新“decsAllowed”常量,如果需要自然数,则更新为 0。
斯威夫特 4
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
}
如果之后您需要将该字符串安全地转换为数字,则可以使用 Double(yourstring) 或 Int(yourstring) 类型转换,或者更学术的方式:
let formatter = NumberFormatter()
let theNumber: NSNumber = formatter.number(from: yourTextField.text)!