UITextField 입력에 숫자 만 허용


82

iPad에는 iPhone / iPod처럼 "Numpad"키보드가 없습니다.

0에서 9까지의 값만 허용하도록 사용자의 키보드를 제한 할 수있는 방법을 찾고 있습니다.

UITextField의 "shouldChangeCharactersInRange"를 사용하는 것을 상상하지만이를 구현하는 가장 좋은 방법을 모르겠습니다.


다운로드 가능한 프로젝트 소스 코드로이를 수행하는 방법에 대한 자습서를 만들었습니다. 여기 : xcodenoobies.blogspot.com/2013/12/…
GeneCode

답변:


86

이것이 SSN 확인 필드에서 문제를 처리하는 방법이며, 최대 길이를 수정하고 if필요한 경우 키보드 유형을 확인 하는 문을 제거 할 수 있습니다.

데이터를 붙여 넣는 대신 사용자가 입력 할 때 최대 길이 경고를 억제하는 논리도 있습니다.

이 코드의 컨텍스트 내에서 전달 된 메시지 문자열을 사용하여 presentAlert()/presentAlert:a 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
}

목표 -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;
}

2
감사! '키보드가 숫자 패드 인 경우 입력에서 잘못된 문자 제거'섹션이 내 질문에 대한 답변을 도왔습니다!
Demasterpl 2010 년

@Gargo 질문은 특별히 허용되는 유일한 값은 0에서 9까지의 숫자 여야한다고 명시합니다. 마침표 문자는 이러한 요구 사항에 해당되지 않습니다. 마침표 문자를 허용하려면 여기 에서 Aje가 제공 한 답을 볼 수 있습니다 .
Beltalowda

이미 사용했지만 선행 0으로 문제가 남습니다
Gargo

@Gargo는 다른 마침표 문자를 감지하는 데 사용하는 것과 유사한 것을 사용할 수 있으며 다음과 같은 경우 0 문자에 대해서만 yes를 반환 할 수 있습니다. 텍스트 필드가 현재 비어 있고 삽입 점이 인덱스 0에 있고 다음 문자가 마침표 인 경우 또는 삽입 지점이 기존 마침표 문자보다 큰 인덱스에있는 경우 적어도 입력되는 0이 선행 0 문제를 일으키지 않는지 확인하는 한 가지 방법입니다.
Beltalowda

26

이 코드를 사용하여 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;
    }

5
btw는이 코드를 사용하는 다른 사용자의 [string intValue]경우 @ "0"에 대해 0을 반환하므로 if ([string intValue])@ "0"에 대해 충족되지 않습니다. 더 나은 사용if ([string rangeOfCharacterFromSet:[[NSCharacterSet decimalDigitCharacterSet] invertedSet]].location != NSNotFound)
CharlesA

2
@".".intValue0입니다. 또한 @"0".intValue0입니다.
Jaybo 2015 년

여기에서 다른 주석을 명확히하기 위해 :이 코드는 사용자가 영 ( 0) 문자를 입력 할 수 없도록 합니다.
Beltalowda 2015

22

텍스트 필드 지우기 문제를 방지하려면 이것을 시도하십시오.

스위프트 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
}

2
델리게이트 방법을 단순화하고 방금 떠났습니다return guard CharacterSet(charactersIn: "0123456789").isSuperset(of: CharacterSet(charactersIn: string))
hamsternik

내 코드에 복사하여 붙여 넣었는데 작동하지 않습니다. 어떻게 연결하고 작동 시키나요?
Yash Jain

먼저 textField 델리게이트 (textField.delegate = self)를 설정하고 UITextFieldDelegate 프로토콜을 준수합니다.
SPatel

19

Swift 코드에 대한 매우 구체적인 단계

프로토콜 func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool을 구현하여 메서드 에서 텍스트 필드의 입력을 제한하는 논리를 제공 할 수 있습니다 UITextFieldDelegate.

명확성을 위해이 단계에서는 스토리 보드에 숫자 만 허용해야하는 텍스트 필드 개체 가있는 View Controller 가 포함되어 있다고 가정합니다 .

  1. 확장하는 뷰 컨트롤러에 대한 사용자 정의 클래스를 만듭니다 UIViewController. Xcode의 Identity Inspector에서 사용자 정의 클래스 값을 설정하여 스토리 보드의 장면이 사용자 정의 클래스를 참조 하는지 확인하십시오 .

    import UIKit
    class YourCustomController: UIViewController {
        override func viewDidLoad() {        
            super.viewDidLoad()
        }
    }
    
  2. 장면의 텍스트 필드에서 사용자 정의 뷰 컨트롤러로의 콘센트를 만듭니다.

    class YourCustomController: UIViewController {
        @IBOutlet weak var numberField: UITextField!
        ...
    }
    
  3. UITextFieldDelegate사용자 정의보기 컨트롤러에 프로토콜을 적용하십시오 .

    class YourCustomController: UIViewController, UITextFieldDelegate {
        ...
    }
    
  4. 커스텀 뷰 컨트롤러의 viewDidLoad메서드에서 텍스트 필드의 델리게이트를 커스텀 뷰 컨트롤러 클래스에 할당합니다.

    override func viewDidLoad() {        
        super.viewDidLoad()
        numberField.delegate = self
    }
    
  5. UITextFieldDelegatefunc textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool메소드를 추가하십시오 .

    numberField이전 단계에서 사용자 정의 뷰 컨트롤러를 의 대리자 로 만든 결과 사용자가 텍스트 필드에 문자를 입력 할 때마다이 메서드가 호출됩니다. 메서드가 반환 true되면 문자가 텍스트 필드에 남아 있습니다. 메서드가 반환 false되면 문자가 텍스트 필드에 남아 있지 않습니다 .

    string매개 변수는 사용자에 의해 입력되는 문자이다. string문자를로 변환 할 수있는 경우 Int0에서 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
    }    
}

10 진수 텍스트 필드가있는보기 컨트롤러 예

십진수를 지원하려면 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
    }    
}

2
이것은 좋지만 빈 문자열을 확인하지 않고 필드에서 아무것도 삭제할 수 없으므로 약간 조정했습니다. 또한 첫 번째 문자 if (string == "-"&& range.location == 0) || string == ""{return true} return string.toInt ()! = nil
ickydime

return string.toInt() != nil 매력처럼 작동했습니다. 감사!
CalZone 2015 년

Swift 2에서 이것을 변경해야했습니다return Int(string) != nil
nevster

@nevster 댓글 주셔서 감사합니다! 대부분의 Swift 개발자는 Swift 2 이상으로 이전했거나 앞으로 이동할 것입니다. 따라서 Swift 2의 string-to-int 변환을 준수하도록 답변을 업데이트했습니다.
whyceewhite 2015

7
한 가지 더 변경해야했습니다. 삭제 키가 더 이상 작동하지 않습니다! 그래서 나는 그것을return string == "" || Int(string) != nil
nevster

9
- (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;
}

1
이것은 오른쪽으로 변경해야하는 분수에 대해 잘 작동합니다. newString : NSString * newString = [textField.text stringByReplacingCharactersInRange : range withString : string];
Idali

7

나는 이것을 적용하고 작동합니다 !!

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

1
추가하려면 ".", 대체 if (character < 48) return NO; // 48 unichar for 0 if (character > 57) return NO; // 57 unichar for 9if ((character < 48 || character > 57) && character != 46)추가로 비교할 추천 할 것입니다 I character헥사 가장 일반적으로 이러한 상황에서 사용되는 같은 숫자의 16 진수 표현에. Ieif ((character < 0x30 || character > 0x39) && character != 0x2E)
Jacob R

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

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

1

Swift에서 :

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

1

스위프트 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에 연결되지 않습니다
Yash Jain

0

내부 표현과 구별되는 프레젠테이션 데이터를 유지합니다. 더 간단한 방법이 있습니다. 일을하자 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]]];

0

사양 패턴 을 사용하면 코드는 다음과 같습니다.

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
}

숫자 만 수신하고 6과 8 사이의 숫자 수를 제한하도록 UITextfield를 어떻게 제한합니까?
Marco Almeida

안녕하세요 @MarcoAlmeida가 제 프레임 워크 SwiftyFORM을 살펴보세요. 실시간 유효성 검사 텍스트 github.com/neoneye/SwiftyFORM
neoneye

0

디지털 작업 및 "."에 대한 @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; 
 }

0

스위프트 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
    }

-1

이 코드를 사용하십시오.

NSString* val = [[textField text] stringByReplacingCharactersInRange:range withString:string];
NSCharacterSet *allowedCharacterSet = [NSCharacterSet decimalDigitCharacterSet];
if ([[string componentsSeparatedByCharactersInSet:[allowedCharacterSet invertedSet]] count] > 1 || [val length] > 5) {
    return NO;
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.