ChatGPT解决这个技术问题 Extra ChatGPT

UITextField 输入只允许数字

iPad 没有像 iPhone/iPod 那样的“Numpad”键盘。

我正在寻找如何将用户的键盘限制为仅接受 0 到 9 的值。

我会想象使用 UITextField 的“shouldChangeCharactersInRange”,但我不知道实现它的最佳方法。

我制作了一个关于如何使用可下载的项目源代码完成此任务的教程。这里:xcodenoobies.blogspot.com/2013/12/…

B
Beltalowda

这是您在 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;
}

谢谢! “如果键盘是数字键盘,则从输入中删除无效字符”部分帮助回答了我的问题!
@Gargo这个问题特别指出,唯一允许的值应该是数字0到9。句点字符不符合这些要求。对于允许句点字符,可以看到 Aje here 给出的答案。
已经使用了它,但它留下了前导零的问题
@Gargo您可以使用类似于他的东西来检测其他句点字符,并且仅在以下情况下对零字符返回yes:文本字段当前为空,如果插入点位于索引0并且下一个字符是句点,或者如果插入点的索引大于现有句点字符的索引。至少这是我可以检查以确保输入的零不会产生前导零问题的一种方法。
A
Aje

您可以使用此代码在 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) 字符。
S
SPatel

试试这个以避免文本字段清除问题

斯威夫特 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))
我复制并粘贴到我的代码上,但不起作用。如何连接并使其工作?
首先设置 textField 委托 (textField.delegate = self) 并符合 UITextFieldDelegate 协议就是这样。
w
whyceewhite

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
    }    
}

这很好,但做了一个小的调整,因为它不允许您在不检查空字符串的情况下删除字段中的任何内容。我还通过检查第一个字符 if (string=="-" && range.location==0) || 添加了否定的能力string=="" { return true } return string.toInt() != nil
return string.toInt() != nil 工作就像一个魅力。谢谢!
请注意,在 Swift 2 中,我必须将其更改为 return Int(string) != nil
我必须进行的另一项更改 - 删除键不再起作用!所以我把它改成了return string == "" || Int(string) != nil
有什么方法可以接受一个“。”来表示小数点?
B
Blazej SLEBODA
- (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;
}

这适用于您需要更改正确的 newString 的分数: NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
p
pkamb

我应用了这个,它有效!

-(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)
Y
Younes Idrissi

迅速 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


你如何实现这个?仅创建此功能不会将其连接到 UITextfield
你必须添加: textField.delegate = self in viewDidLoad()
j
johnny
NSString* val = [[textField text] stringByReplacingCharactersInRange:range withString:string];
    NSCharacterSet *allowedCharacterSet = [NSCharacterSet decimalDigitCharacterSet];
    if ([[string componentsSeparatedByCharactersInSet:[allowedCharacterSet invertedSet]] count] > 1 || [val length] > 5) {
        return NO;
    }

A
Ankit Kumar Gupta
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;
    }

m
mishimay

在斯威夫特:

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        return string.isEmpty || Int(string) != nil
    }

g
gdm

保持与内部表示不同的表示数据。有一个更简单的方法。让 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]]];

n
neoneye

如果您使用我的 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
}

如何将 UITextfield 限制为仅接收数字并将数字数量限制在 6 到 8 之间?
嗨 @MarcoAlmeida 看看我的框架 SwiftyFORM,它可以实时验证文本,github.com/neoneye/SwiftyFORM
H
Hiren

我已经修改了@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; 
 }

A
ArgaPK

迅速 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
    }

p
pii_ke

使用此代码:

NSString* val = [[textField text] stringByReplacingCharactersInRange:range withString:string];
NSCharacterSet *allowedCharacterSet = [NSCharacterSet decimalDigitCharacterSet];
if ([[string componentsSeparatedByCharactersInSet:[allowedCharacterSet invertedSet]] count] > 1 || [val length] > 5) {
    return NO;
}