iPad 没有像 iPhone/iPod 那样的“Numpad”键盘。
我正在寻找如何将用户的键盘限制为仅接受 0 到 9 的值。
我会想象使用 UITextField 的“shouldChangeCharactersInRange”,但我不知道实现它的最佳方法。
这是您在 SSN 验证字段上处理问题的方式,如果需要,您可以修改最大长度并删除 if
语句检查键盘类型。
当用户键入而不是粘贴数据时,还有一种逻辑可以抑制最大长度警报。
在此代码的上下文中,presentAlert()/presentAlert:
只是一些基本函数,它使用传递的消息字符串呈现 UIAlertController
(或旧版 UIAlertView
)。
斯威夫特 5
// 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.
//
// There are also some better stylistic approaches in Swift to avoid all the
// nested statements, but I wanted to keep the styles similar to allow others
// to contrast and compare between the two languages a little easier.
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
// Handle backspace/delete
guard !string.isEmpty else {
// Backspace detected, allow text change, no need to process the text any further
return true
}
// Input Validation
// Prevent invalid character input, if keyboard is numberpad
if textField.keyboardType == .numberPad {
// Check for invalid input characters
if CharacterSet(charactersIn: "0123456789").isSuperset(of: CharacterSet(charactersIn: string)) {
// Present alert so the user knows what went wrong
presentAlert("This field accepts only numeric entries.")
// Invalid characters detected, disallow text change
return false
}
}
// Length Processing
// Need to convert the NSRange to a Swift-appropriate type
if let text = textField.text, let range = Range(range, in: text) {
let proposedText = text.replacingCharacters(in: range, with: string)
// Check proposed text length does not exceed max character count
guard proposedText.count <= maxCharacters else {
// Present alert if pasting text
// easy: pasted data has a length greater than 1; who copy/pastes one character?
if string.count > 1 {
// Pasting text, present alert so the user knows what went wrong
presentAlert("Paste failed: Maximum character count exceeded.")
}
// Character count exceeded, disallow text change
return false
}
// 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, etc)
answerButton.isEnabled = (proposedText.count == 4)
}
// Allow text change
return true
}
Objective-C
// 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
{
// Handle backspace/delete
if (!string.length)
{
// Backspace detected, allow text change, no need to process the text any further
return YES;
}
// Input Validation
// Prevent invalid character input, if keyboard is numberpad
if (textField.keyboardType == UIKeyboardTypeNumberPad)
{
if ([string rangeOfCharacterFromSet:[NSCharacterSet decimalDigitCharacterSet].invertedSet].location != NSNotFound)
{
[self presentAlert: @"This field accepts only numeric entries."];
return NO;
}
}
// Length Validation
NSString *proposedText = [textField.text stringByReplacingCharactersInRange:range withString:string];
// Check proposed text length does not exceed max character count
if (proposedText.length > maxCharacters)
{
// Present alert if pasting text
// easy: pasted data has a length greater than 1; who copy/pastes one character?
if (string.length > 1)
{
// Pasting text, present alert so the user knows what went wrong
[self presentAlert: @"Paste failed: Maximum character count exceeded."];
}
// Character count exceeded, disallow text change
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, etc)
self.answerButton.enabled = (proposedText.length == maxCharacters);
// Allow text change
return YES;
}
您可以使用此代码在 textField 中只允许数字。
在为 textField 设置委托之前
textFieldName.delegate=self;
或者
[textFieldName setDelegate:self];
比使用此代码仅允许数字到 textField
- (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;
}
[string intValue]
为 @"0" 返回 0 - 因此对于 @"0" 不满足 if ([string intValue])
。最好使用 if ([string rangeOfCharacterFromSet:[[NSCharacterSet decimalDigitCharacterSet] invertedSet]].location != NSNotFound)
@".".intValue
为 0。@"0".intValue
也为 0。
0
) 字符。
试试这个以避免文本字段清除问题
斯威夫特 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
}
斯威夫特 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
}
return guard CharacterSet(charactersIn: "0123456789").isSuperset(of: CharacterSet(charactersIn: string))
Swift 代码的非常具体的步骤
您可以通过实现 UITextFieldDelegate
协议,在 func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool
方法中提供限制文本字段输入的逻辑。
为了清楚起见,这些步骤假设您的故事板包含一个视图控制器,该控制器带有一个只接受数字的文本字段对象。
为扩展 UIViewController 的视图控制器创建一个自定义类。通过在 Xcode 的 Identity Inspector 中设置自定义类值,确保情节提要中的场景引用自定义类。 import UIKit class YourCustomController: UIViewController { override func viewDidLoad() { super.viewDidLoad() } } 创建从场景文本字段到自定义视图控制器的出口。类YourCustomController:UIViewController {@IBOutlet 弱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 的委托,因此每次用户在文本字段中输入字符时都会调用此方法。如果您的方法返回 true,则该字符将保留在文本字段中。如果您的方法返回 false,则该字符将不会保留在文本字段中。字符串参数是用户输入的字符。如果字符串字符可以转换为 Int,那么它在 0 和 9 之间;否则,它是一些非数字字符。类 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
}
}
return string.toInt() != nil
工作就像一个魅力。谢谢!
return Int(string) != nil
return string == "" || Int(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 total length for restrict user
NSUInteger proposedNewLength = textField.text.length - range.length + string.length;
if (proposedNewLength > 6)
return YES;
return YES;
}
if (character < 48) return NO; // 48 unichar for 0 if (character > 57) return NO; // 57 unichar for 9
替换为 if ((character < 48 || character > 57) && character != 46)
我还建议您将 character
与数字的十六进制表示进行比较,因为在这些情况下最常使用十六进制。即if ((character < 0x30 || character > 0x39) && character != 0x2E)
迅速 5
//MARK:- UITextFieldDelegate
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let allowedCharacters = "1234567890"
let allowedCharcterSet = CharacterSet(charactersIn: allowedCharacters)
let typedCharcterSet = CharacterSet(charactersIn: string)
return allowedCharcterSet.isSuperset(of: typedCharcterSet)
}
您现在只能点击 1234567890
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;
}
在斯威夫特:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
return string.isEmpty || Int(string) != nil
}
保持与内部表示不同的表示数据。有一个更简单的方法。让 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]]];
如果您使用我的 specification pattern,则代码如下所示
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;
}
迅速 3
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if textField==yourTextFieldOutlet {
if(CharacterSet.decimalDigits.isSuperset(of: CharacterSet(charactersIn: yourTextFieldOutlet.text!))){
//if numbers only, then your code here
}
else{
showAlert(title: "Error",message: "Enter Number only",type: "failure")
}
}
return true
}
使用此代码:
NSString* val = [[textField text] stringByReplacingCharactersInRange:range withString:string];
NSCharacterSet *allowedCharacterSet = [NSCharacterSet decimalDigitCharacterSet];
if ([[string componentsSeparatedByCharactersInSet:[allowedCharacterSet invertedSet]] count] > 1 || [val length] > 5) {
return NO;
}