只允许UITextFieldinput的数字
iPad没有像iPhone / iPod那样的“Numpad”键盘。
我正在寻找如何限制用户的键盘只能接受0到9的值。
我会想象使用UITextField的“shouldChangeCharactersInRange”,但我不知道实现它的最好方法。
这是我如何处理SSNvalidation字段上的问题,如果需要,可以修改最大长度并删除if
语句检查键盘types。
还有一种逻辑是在用户input时抑制最大长度警报,而不是粘贴数据。
在此代码的上下文中, BasicAlert()
是一个#define
macros,它简单地显示了使用传递的标题和消息string的UIAlertView
或UIAlertController
。
// NOTE: This code assumes you have set the UITextField(s)'s delegate property to the object that will contain this code, because otherwise it would never be called. - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { // allow backspace if (!string.length) { return YES; } // Prevent invalid character input, if keyboard is numberpad if (textField.keyboardType == UIKeyboardTypeNumberPad) { if ([string rangeOfCharacterFromSet:[NSCharacterSet decimalDigitCharacterSet].invertedSet].location != NSNotFound) { // BasicAlert(@"", @"This field accepts only numeric entries."); return NO; } } // verify max length has not been exceeded NSString *proposedText = [textField.text stringByReplacingCharactersInRange:range withString:string]; if (proposedText.length > 4) // 4 was chosen for SSN verification { // suppress the max length message only when the user is typing // easy: pasted data has a length greater than 1; who copy/pastes one character? if (string.length > 1) { // BasicAlert(@"", @"This field accepts a maximum of 4 characters."); } return NO; } // only enable the OK/submit button if they have entered all numbers for the last four of their SSN (prevents early submissions/trips to authentication server) self.answerButton.enabled = (proposedText.length == 4); return YES; }
您可以使用此代码只允许textField中的数字。
在那之前为textField设置委托
textFieldName.delegate=self;
要么
[textFieldName setDelegate:self];
比使用这个代码只允许数字到文本字段
- (BOOL) textField: (UITextField *)theTextField shouldChangeCharactersInRange:(NSRange)range replacementString: (NSString *)string { //return yes or no after comparing the characters // allow backspace if (!string.length) { return YES; } ////for Decimal value start//////This code use use for allowing single decimal value // if ([theTextField.text rangeOfString:@"."].location == NSNotFound) // { // if ([string isEqualToString:@"."]) { // return YES; // } // } // else // { // if ([[theTextField.text substringFromIndex:[theTextField.text rangeOfString:@"."].location] length]>2) // this allow 2 digit after decimal // { // return NO; // } // } ////for Decimal value End//////This code use use for allowing single decimal value // allow digit 0 to 9 if ([string intValue]) { return YES; } return NO; }
Swift代码的非常具体的步骤
您可以通过实现UITextFieldDelegate
协议来提供限制func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool
方法中的文本字段input的逻辑。
为了清楚起见,这些步骤假设您的故事板包含一个带有文本字段对象的视图控制器 ,该对象只能接受数字。
-
为扩展
UIViewController
的视图控制器创build一个自定义的类。 确保故事板中的场景通过在Xcode的Identity Inspector中设置自定义类的值来引用自定义类。import UIKit class YourCustomController: UIViewController { override func viewDidLoad() { super.viewDidLoad() } }
-
从您的场景的文本字段创build一个出口到您的自定义视图控制器。
class YourCustomController: UIViewController { @IBOutlet weak var numberField: UITextField! ... }
-
在自定义视图控制器中应用
UITextFieldDelegate
协议。class YourCustomController: UIViewController, UITextFieldDelegate { ... }
-
在您的自定义视图控制器的
viewDidLoad
方法中,将您的文本字段的委托分配给您的自定义视图控制器类。override func viewDidLoad() { super.viewDidLoad() numberField.delegate = self }
-
添加
UITextFieldDelegate
的func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool
方法。作为在上一步
numberField
自定义视图控制器设置为numberField
的委托的结果,每次用户在文本字段中input字符时都会调用此方法。 如果你的方法返回true
那么这个字符将保留在文本字段中。 如果你的方法返回false
那么这个字符将不会保留在文本字段中。string
参数是用户input的字符。 如果string
字符可以转换为一个Int
然后它是在0和9之间; 否则,它是一些非数字字符。class YourCustomController: UIViewController, UITextFieldDelegate { ... func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { return Int(string) != nil } }
(请参阅下面的全视图控制器代码。)
示例视图控制器仅包含数字的文本字段
import UIKit class YourCustomController: UIViewController, UITextFieldDelegate { @IBOutlet weak var numberField: UITextField! override func viewDidLoad() { super.viewDidLoad() numberField.delegate = self } func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { return Int(string) != nil } }
带有十进制文本字段的示例视图控制器
如果你想支持一个十进制数然后利用NSNumberFormatter
。 查看代码评论的差异。
import UIKit class YourCustomController: UIViewController, UITextFieldDelegate { @IBOutlet weak var numberField: UITextField! private var formatter: NSNumberFormatter! override func viewDidLoad() { super.viewDidLoad() numberField.delegate = self // Initialize the formatter; minimum value is set to zero; style is Decimal. formatter = NSNumberFormatter() formatter.numberStyle = NSNumberFormatterStyle.DecimalStyle formatter.minimum = 0 } func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { // Combine the current text field value and the new string // character. If it conforms to the formatter's settings then // it is valid. If it doesn't then nil is returned and the // string character should not be allowed in the text field. return formatter.numberFromString("\(textField.text)\(string)") != nil } }
- (BOOL) textField: (UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString: (NSString *)string { NSNumberFormatter * nf = [[NSNumberFormatter alloc] init]; [nf setNumberStyle:NSNumberFormatterNoStyle]; NSString * newString = [NSString stringWithFormat:@"%@%@",textField.text,string]; NSNumber * number = [nf numberFromString:newString]; if (number) return YES; else return NO; }
我应用这个,它的工作原理!
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{ // Check for non-numeric characters NSUInteger lengthOfString = string.length; for (NSInteger index = 0; index < lengthOfString; index++) { unichar character = [string characterAtIndex:index]; if (character < 48) return NO; // 48 unichar for 0 if (character > 57) return NO; // 57 unichar for 9 } // Check for total length NSUInteger proposedNewLength = textField.text.length - range.length + string.length; if (proposedNewLength > 6) return YES; return YES; }
NSString* val = [[textField text] stringByReplacingCharactersInRange:range withString:string]; NSCharacterSet *allowedCharacterSet = [NSCharacterSet decimalDigitCharacterSet]; if ([[string componentsSeparatedByCharactersInSet:[allowedCharacterSet invertedSet]] count] > 1 || [val length] > 5) { return NO; }
Works fine for me : - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { if (([string rangeOfCharacterFromSet:[[NSCharacterSet decimalDigitCharacterSet] invertedSet]].location != NSNotFound) && !(range.length==1 && string.length==0)) { return NO; } return YES; }
试试这个以避免文本框清除问题
Swift 3.0
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { guard NSCharacterSet(charactersInString: "0123456789").isSupersetOfSet(NSCharacterSet(charactersInString: string)) else { return false } return true }
Swift 4.0
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { guard CharacterSet(charactersIn: "0123456789").isSuperset(of: CharacterSet(charactersIn: string)) else { return false } return true }
保持内部表示不同的演示数据。 有一个更简单的方法。 让NSNumberFormatter
做这个工作:
NSNumberFormatter* ns = [[NSNumberFormatter alloc] init]; ns.numberStyle = NSNumberFormatterDecimalStyle; [ns setMaximumFractionDigits:2]; // This is your internal representation of the localized number double a = [[ns numberFromString:self.textIVA.text] doubleValue]]; [mylabel setText:[NSString stringWithFormat:@"€ %@", [NSNumberFormatter localizedStringFromNumber: [NSNumber numberWithDouble:a] numberStyle:NSNumberFormatterDecimalStyle]]];
如果你使用我的规范模式,那么代码看起来像这样
textField.delegate = self lazy var specification: Specification = { return RegularExpressionSpecification(pattern: "^(|0|[1-9]\\d{0,6})$") }() func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { let textFieldString: NSString = textField.text ?? "" let s = textFieldString.stringByReplacingCharactersInRange(range, withString:string) return specification.isSatisfiedBy(s) } func textFieldShouldReturn(textField: UITextField) -> Bool { let s = textField.text ?? "" let isTextValid = specification.isSatisfiedBy(s) if isTextValid { textField.resignFirstResponder() } return false }
我已经修改@ iDev的答案为数字和“。”工作:
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{ // Check for non-numeric characters NSUInteger lengthOfString = string.length; for (NSInteger index = 0; index < lengthOfString; index++) { unichar character = [string characterAtIndex:index]; if ((character < 48) && (character != 46)) return NO; // 48 unichar for 0, and 46 unichar for point if (character > 57) return NO; // 57 unichar for 9 } // Check for total length NSUInteger proposedNewLength = textField.text.length - range.length + string.length; if (proposedNewLength > 6) return YES; return YES; }
使用此代码:
NSString* val = [[textField text] stringByReplacingCharactersInRange:range withString:string]; NSCharacterSet *allowedCharacterSet = [NSCharacterSet decimalDigitCharacterSet]; if ([[string componentsSeparatedByCharactersInSet:[allowedCharacterSet invertedSet]] count] > 1 || [val length] > 5) { return NO; }