IT박스

Swift에서 숫자 만 취하도록 UITextField를 제한하는 방법은 무엇입니까?

itboxs 2020. 11. 29. 10:08
반응형

Swift에서 숫자 만 취하도록 UITextField를 제한하는 방법은 무엇입니까?


사용자가 UITextField. iPhone에서는 숫자 키보드를 표시 할 수 있지만 iPad에서는 사용자가 모든 키보드로 전환 할 수 있습니다.

사용자가 숫자 값만 입력하도록 제한하는 방법이 UITextField있습니까?


여기 제 2 센트가 있습니다. (Swift 2에서만 테스트 됨)

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {

  let aSet = NSCharacterSet(charactersInString:"0123456789").invertedSet
  let compSepByCharInSet = string.componentsSeparatedByCharactersInSet(aSet)
  let numberFiltered = compSepByCharInSet.joinWithSeparator("")
  return string == numberFiltered

}

이것은 조금 더 엄격합니다. 소수점도 없습니다.

도움이되기를 바랍니다 :)

추신 : 어쨌든 대의원을 돌보 셨다고 생각했습니다.

업데이트 : Swift 3.0 :

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

    let aSet = NSCharacterSet(charactersIn:"0123456789").inverted
    let compSepByCharInSet = string.components(separatedBy: aSet)
    let numberFiltered = compSepByCharInSet.joined(separator: "")
    return string == numberFiltered
}

신속한 3.0 이상을위한 솔루션

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool
  {
    let allowedCharacters = CharacterSet.decimalDigits
    let characterSet = CharacterSet(charactersIn: string)
    return allowedCharacters.isSuperset(of: characterSet)
  }

신속한 4.1 및 Xcode 9.4.1

클래스에 UITextFieldDelegate 추가

class YourViewController: UIViewController, UITextFieldDelegate

그런 다음 viewDidLoad () 에이 코드를 작성합니다.

mobileNoTF.delegate = self

이 텍스트 필드 대리자 함수 작성

//MARK - UITextField Delegates
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    //For mobile numer validation
    if textField == mobileNoTF {
        let allowedCharacters = CharacterSet(charactersIn:"+0123456789 ")//Here change this characters based on your requirement
        let characterSet = CharacterSet(charactersIn: string)
        return allowedCharacters.isSuperset(of: characterSet)
    }
    return true
}

스위프트 2.0

숫자와 하나의 "."만 허용합니다. uitextfield의 10 진수.

func textField(textField: UITextField,shouldChangeCharactersInRange range: NSRange,replacementString string: String) -> Bool
{
    let newCharacters = NSCharacterSet(charactersInString: string)
    let boolIsNumber = NSCharacterSet.decimalDigitCharacterSet().isSupersetOfSet(newCharacters)
    if boolIsNumber == true {
        return true
    } else {
        if string == "." {
            let countdots = textField.text!.componentsSeparatedByString(".").count - 1
            if countdots == 0 {
                return true
            } else {
                if countdots > 0 && string == "." {
                    return false
                } else {
                    return true
                }
            }
        } else {
            return false
        }
    }
}

Swift 3에서 단일 (.) 점으로 텍스트 필드에 10 진수 값 허용

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

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    // return true if the replacementString only contains numeric characters
    let digits = NSCharacterSet.decimalDigitCharacterSet()
    for c in string {
        if !digits.characterIsMember(c) {
            return false
        }
    }

    return true
}

이 솔루션은 사용자가 키보드를 전환하거나 숫자가 아닌 문자열을 텍스트 필드에 붙여 넣으려는 경우에도 작동합니다.

delegate적절한 텍스트 필드 속성 을 설정해야 합니다.


아이폰 전용 솔루션

이러한 값을 가져 오는 UITextField에서 누군가 텍스트 필드 내부를 터치 할 때 표시 할 키보드의 종류를 지정할 수 있습니다.

예 : 숫자 전용 키보드.

이 스크린 샷처럼 :

여기에 이미지 설명 입력

Ipad

iPad는 숫자 키보드를 지원하지 않으므로 옵션은 iPad를 지원하지 않거나 필드 포스트 제출을 확인하거나 여기에있는 다른 제안 중 하나를 따라 iPad에서 실행하는 동안 정상적인 동작을 만드는 것입니다.


숫자 포맷터 사용

스위프트 4.x

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
      let s = NSString(string: textField.text ?? "").replacingCharacters(in: range, with: string)
      guard !s.isEmpty else { return true }
      let numberFormatter = NumberFormatter()
      numberFormatter.numberStyle = .none
      return numberFormatter.number(from: s)?.intValue != nil
 }

다음은 간단한 해결책입니다. "Editing changed"이벤트를 컨트롤러의이 메서드에 연결해야합니다.

스위프트 4

@IBAction func valueChanged(_ sender: UITextField) {
    if let last = sender.text?.last {
        let zero: Character = "0"
        let num: Int = Int(UnicodeScalar(String(last))!.value - UnicodeScalar(String(zero))!.value)
        if (num < 0 || num > 9) {
            //remove the last character as it is invalid
            sender.text?.removeLast()
        }
    }
}

Big Nerd Ranch 책을 통해 작업 할 때 실제로이 작업을 수행했습니다. 내 솔루션은 다음과 같습니다.

func textField(textField: UITextField, 
    shouldChangeCharactersInRange range: NSRange, 
    replacementString string: String) -> Bool {

    let newCharacters = NSCharacterSet(charactersInString: string)
    return NSCharacterSet.decimalDigitCharacterSet().isSupersetOfSet(newCharacters)
}

이것은 "."를 허용하기 위해 숫자 0-9 만 허용합니다. 또한 "."는 하나만 허용 할 수 있으므로 더 복잡합니다.


이러한 솔루션의 대부분이 작동하지만 일부 지역화에서는 소수가 "."가 아닌 ""로 구분된다는 점에 유의하십시오.

이를 수행하는 더 깨끗한 방법은

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    let decimalCharacter = NSNumberFormatter().decimalSeparator
    let characterSet = NSMutableCharacterSet.decimalDigitCharacterSet()
    characterSet.addCharactersInString(decimalCharacter)

    return replacementString.rangeOfCharacterFromSet(characterSet.invertedSet) == nil
}

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    if let numRange = string.rangeOfCharacterFromSet(NSCharacterSet.letterCharacterSet()) {
        return false
    } else {
        return true
    }
   }

숫자와 소수 연산자 하나만 허용하려면 다음 솔루션을 사용할 수 있습니다.

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    let isNumber = NSCharacterSet.decimalDigitCharacterSet().isSupersetOfSet(NSCharacterSet(charactersInString: string))

    return isNumber || (string == NSNumberFormatter().decimalSeparator && textField.text?.containsString(string) == false)
}

신속한 3.0에서 테스트

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool

{         
    let numberOnly = NSCharacterSet.init(charactersIn: "0123456789")
    let stringFromTextField = NSCharacterSet.init(charactersIn: string)
    let strValid = numberOnly.isSuperset(of: stringFromTextField as CharacterSet)

     return strValid
 }

다음과 같이 뷰 컨트롤러를 확장하십시오.

class MyViewController: UIViewController, UITextFieldDelegate

viewDidLoad 함수에서 다음과 같이 텍스트 필드로 확장합니다.

myTextField.delegate = self

그리고 다음 기능을 사용하십시오.

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    let isNumber = CharacterSet.decimalDigits.isSuperset(of: CharacterSet(charactersIn: string))
    let withDecimal = (
        string == NumberFormatter().decimalSeparator &&
        textField.text?.contains(string) == false
    )
    return isNumber || withDecimal
}

이제 사용자가 십진수 만 입력 할 수 있습니다.

Swift 4 + 숫자 만 허용하고 구분 기호 하나만 허용


첫 번째는 자신의 클래스와 함께 UITextFieldDelegate 클래스를 상속해야합니다.

class ViewController: UIViewController, UITextFieldDelegate {

두 번째 IBOutlet 추가

@IBOutlet weak var firstName: UITextField!

세 번째로이 개체가 사용하고 있는지 확인해야합니다.

override func viewDidLoad() {
        super.viewDidLoad()
   firstName.delegate = self
}


func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    if textField == firstName {
                let allowedCharacters = "1234567890"
                let allowedCharacterSet = CharacterSet(charactersIn: allowedCharacters)
                let typedCharacterSet = CharacterSet(charactersIn: string)
                let alphabet = allowedCharacterSet.isSuperset(of: typedCharacterSet)
                return alphabet


      }
  }

UITextInputTraits 프로토콜, 선택적 var keyboardType을 구현하여 키보드 유형을 강제로 변경할 수 있다고 생각합니다.

//class ViewController: UIViewController, UITextInputTraits {

@IBOutlet weak var textFieldKeyboardType: UITextField!{
    didSet{
        textFieldKeyboardType.keyboardType = UIKeyboardType.NumberPad
    }
}
var keyboardType: UIKeyboardType { 
    get{ 
        return textFieldKeyboardType.keyboardType
    } 
    set{ 
        if newValue != UIKeyboardType.NumberPad{
            self.keyboardType = UIKeyboardType.NumberPad
        }
    } 
}

대답이 충분하지 않은 것처럼 여기에 내 것이 있습니다. 소수 구분 기호에 허용되는 모든 예는 지역화, 백 스페이스 또는 복사 / 붙여 넣기에 결함이 있다고 생각합니다.

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    if string.isEmpty {return true} //allow for backspace

    let decimalSeparator = NSNumberFormatter().decimalSeparator ?? "."
    let validChars = NSMutableCharacterSet(charactersInString: decimalSeparator)
    validChars.formUnionWithCharacterSet(NSCharacterSet.decimalDigitCharacterSet())

    if validChars.isSupersetOfSet(NSCharacterSet(charactersInString: string)){
        switch string.componentsSeparatedByString(decimalSeparator).count-1 {
        case 0: //no decimals
            return true

        case 1: //if adding decimal, only allow if no existing decimal
            if let existingText = textField.text{
                return existingText.componentsSeparatedByString(decimalSeparator).count <= 1
            }
            else {return true}

        default: //invalid decimals
            return false
        }
    }

    return false
}

다음은 Mr H의 코드를 적용한 Swift 3.0에서 사용한 코드입니다. 차이점은 다음과 같습니다.

a) 위임 함수 선언이 Swift 3.0에서 변경되었습니다. 여기에 새로운 선언

b) NSCharacterSet 선언이 변경되었습니다.

func textField(_ shouldChangeCharactersIntextField: 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: "")

        return string == filtered

}

나는 하나의 점 또는 하나의 쉼표를 허용하도록 Raj Joshi의 버전을 편집했습니다.

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

    let inverseSet = CharacterSet(charactersIn:"0123456789").inverted
    let components = string.components(separatedBy: inverseSet)
    let filtered = components.joined(separator: "")

    if filtered == string {
        return true
    } else {
        if string == "." || string == "," {
            let countDots = textField.text!.components(separatedBy:".").count - 1
            let countCommas = textField.text!.components(separatedBy:",").count - 1

            if countDots == 0 && countCommas == 0 {
                return true
            } else {
                return false
            }
        } else  {
            return false
        }
    }
}

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool

        {
            let textString = (textField.text! as NSString).replacingCharacters(in: range, with: string)

            if textField == self.phoneTextField  && string.characters.count > 0{
                let numberOnly = NSCharacterSet.decimalDigits
                let strValid = numberOnly.contains(UnicodeScalar.init(string)!)
                return strValid && textString.characters.count <= 10
            }
            return true
        }

위의 코드는 신속한 3
NSCharacterSet 에서 작동 합니다. decimalDigits
또한
NSCharacterSet 문자 만 사용합니다 . 문자
대문자, 소문자 및 영숫자, 공백 은 동일한 코드를 사용하거나 링크를 참조하십시오.


일부 캐릭터 허용

func CheckAddress(string:String) -> Bool  {
        let numberOnly = NSCharacterSet.init(charactersIn: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-@,&#/")
        let stringFromTextField = NSCharacterSet.init(charactersIn: string)
        return numberOnly.isSuperset(of: stringFromTextField as CharacterSet)
    }

print("\(CheckAddress(string: "123"))") //True
print("\(CheckAddress(string: "asdf-"))") //True
print("\(CheckAddress(string: "asd123$"))") //false

다음은 더 깨끗한 솔루션입니다.

 guard CharacterSet(charactersIn: "123456789").isSuperset(of: CharacterSet(charactersIn: string)) else {
     return false
 }
 return true

소수의 경우 추가하십시오 ..123456789.


Swift 2.0

func textField(textField: UITextField,
    shouldChangeCharactersInRange range: NSRange,
    replacementString string: String) -> Bool {

        let inverseSet = NSCharacterSet(charactersInString:"0123456789").invertedSet

        let components = string.componentsSeparatedByCharactersInSet(inverseSet)

        let filtered = components.joinWithSeparator("")

        return string == filtered

  }

다음은 "0-9"와 "."을 더한 더 읽기 쉬운 버전입니다.

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {

    let existingTextHasDecimal = textField.text?.rangeOfString(".")
    let replacementTextHasDecimal = string.rangeOfString(".")
    let replacementTextAllCharacters = NSCharacterSet(charactersInString: string)
    let replacementTextOnlyDigits = NSCharacterSet.decimalDigitCharacterSet().isSupersetOfSet(replacementTextAllCharacters)

    if replacementTextHasDecimal != nil && existingTextHasDecimal != nil {
        return false
    }else{
        if replacementTextOnlyDigits == true {
            return true
        }else if replacementTextHasDecimal != nil{
            return true
        }else{
            return false
        }
    }
}

func isValidNumber(str:String) -> Bool{
    if str.isEmpty {
        return false
    }
    let newChar = NSCharacterSet(charactersInString: str)
    let boolValid = NSCharacterSet.decimalDigitCharacterSet().isSupersetOfSet(newChar)
    if boolValid{
        return true
    }else{
        let lst = str.componentsSeparatedByString(".")
        let newStr = lst.joinWithSeparator("")
        let currentChar = NSCharacterSet(charactersInString: newStr)
        if lst.count == 2 && !lst.contains("") && NSCharacterSet.decimalDigitCharacterSet().isSupersetOfSet(currentChar){
            return true
        }
        return false
    }
}

이 기능이있는 경우 "제출"또는 "저장"방법에 넣으십시오.


shouldChangeCharactersInRange를 String 확장 메서드와 함께 사용하여 입력 문자열이 숫자인지 여부를 확인할 수 있습니다.

extension String  {

    var isNumber : Bool {
        get{
            return !self.isEmpty && self.stringWithoutWhitespaces.rangeOfCharacter(from: CharacterSet.decimalDigits.inverted) == nil
        }
    }

    var stringWithoutWhitespaces: String {
        return self.replacingOccurrences(of: " ", with: "")
    }

}

//Mark: shouldChangeCharactersInRange
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    // return true if the string only contains numeric characters
    let isValid = string.stringWithoutWhitespaces.isNumber 
    return valid
}

대리자 Double에서 숫자에 대한 죽은 간단한 솔루션 (이는 최상의 사용자 친화적 인 솔루션이 아니라는 점에 유의하십시오) UITextFieldDelegate:

func textField(_ textField: UITextField,
               shouldChangeCharactersIn range: NSRange,
               replacementString string: String) -> Bool {
        guard let currentString = textField.text as NSString? else {
            return false
        }
        let newString = currentString.replacingCharacters(in: range, with: string)
        return Double(newString) != nil
}

소수 구분 기호 및 / 또는 음수를 허용하려는 경우이 코드를 사용할 수 있습니다. 그러나이 코드는 "34"예를 허용합니다. (끝의 소수점 구분 기호) 텍스트를 변경하는 동안. 따라서 textFieldShouldReturn 또는 textFieldShouldEndEditing 대리자 함수와 같은 코드 예제를 추가해야합니다.

Swift 4로 작성된 코드는 Swift 3과 호환됩니다.

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    guard let text = textField.text else {
        return true
    }

    let replaced = (text as NSString).replacingCharacters(in: range, with: string)
    let decimalSeparator = NSLocale.current.decimalSeparator ?? ""

    // When user wants to delete las character
    if replaced == "" || replaced == "-" || replaced == "-0" {
        textField.text = "0"
        return false
    }

    // When text contains 0 before replace except "0."
    if replaced != "0" + decimalSeparator && replaced.hasPrefix("0") && text.underestimatedCount == 1 {
        textField.text = replaced.substring(from: replaced.index(after: replaced.startIndex))
        return false
    }

    // When user wants to delete minus sign
    if text.hasPrefix("-") && text.substring(from: text.index(after: text.startIndex)) == replaced {
        return false
    }

    // When user wants to delete before decimal separator
    if replaced.hasPrefix(decimalSeparator) || replaced.hasPrefix("-" + decimalSeparator) {
        return false
    }

    // When user wants to add zero the beginning of number... but allowing "0." or "-0." numbers
    let testReplaced = replaced.hasPrefix("-") ? replaced.substring(from: replaced.index(after: replaced.startIndex)) : replaced
    if testReplaced.count >= 2 && testReplaced.hasPrefix("0") && !testReplaced.hasPrefix("0" + decimalSeparator) {
        return false
    }

    // Every other cases
    let allowDecimal = self.allowFloat ? (decimalSeparator == "." ? "\\.?" : decimalSeparator + "?") : ""
    let allowSign = self.allowSigned ? "-?" : ""
    let pattern = "\(allowSign)[0-9]+\(allowDecimal)([0-9]+)?"

    do {
        let regexRange = (replaced as NSString).range(of: replaced)
        let regex = try NSRegularExpression(pattern: pattern, options: [])
        let matches = regex.matches(in: replaced, options: [], range: regexRange)
        return matches.count == 1 && matches.first!.range == regexRange
    }
    catch {}

    return false
}

십진수 나 음수를 허용하지 않으려면 tow 변수를 다음 줄로 바꿔야합니다.

let allowDecimal = ""
let allowSign = ""

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

참고 URL : https://stackoverflow.com/questions/30973044/how-to-restrict-uitextfield-to-take-only-numbers-in-swift

반응형