programing

스위프트에서 UITextField가 숫자만 가져가도록 제한하는 방법은?

closeapi 2023. 10. 18. 22:07
반응형

스위프트에서 UITextField가 숫자만 가져가도록 제한하는 방법은?

사용자가 숫자 값만 입력하도록 합니다.UITextField수 아이패드에서는 로도 바꿀수 . 아이폰에서는 숫자 키보드를 보여줄 수 있지만 아이패드에서는 어떤 키보드로도 바꿀 수 있습니다.

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


참고: 이 질문은 오래된 질문으로 답이 많습니다.게시된 답변의 3분의 1 이상이 틀렸습니다.심지어 높은 지지를 받은 몇몇 답변들도 틀렸습니다.이 질문을 아직 보여주지 않은 방식으로 해결할 수 있는 매우 개선된 방법을 찾지 않는 한 새로운 답변을 게시하지 마십시오.당신의 대답이 모든 상황에서 효과가 있는지 확인하세요.그것은 아이폰과 아이패드 모두에 효과가 있어야 합니다.사용자가 텍스트 필드에 텍스트를 붙여넣을 때 작동해야 합니다.사용자가 외장 키보드를 가지고 있는 경우에는 반드시 작동해야 합니다.텍스트를 입력하거나 붙여넣기 전에 사용자가 텍스트 필드의 텍스트 선택을 변경하는 경우 이 옵션이 작동해야 합니다.십진 숫자(사용자 로케일에 적합한 십진 구분자 하나)를 적절하게 지원해야 합니다.

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

여기 제 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

}

이것은 단지 조금 더 엄격할 뿐입니다.소수점도 없습니다.

도움이 되길 바랍니다 :)

추신: 저는 당신이 대표님을 돌본 줄 알았습니다.

업데이트: 스위프트 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
}

In swift 4.1 및 Xcode 9.4.1

클래스에 UITTextFieldDelegate 추가

class YourViewController: UIViewController, UITextFieldDelegate

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

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
}

아이폰

이러한 값을 가져오는 UITTextField에서는 텍스트 필드 내부를 터치할 때 나타날 키보드 종류를 지정할 수 있습니다.

예를 들면 숫자로만 된 키보드

이 스크린샷처럼:

enter image description here

아이패드

iPad는 숫자 키보드를 지원하지 않으므로 iPad를 지원하지 않거나, 게시물 제출 필드의 유효성을 확인하거나, iPad에서 실행되는 동안 동일한 동작을 만들기 위해 여기에 있는 다른 제안 사항 중 하나를 따르는 것이 좋습니다.

스위프트 2.0

uitext 필드에 숫자와 "." 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에서 점(.dot)이 하나인 텍스트 필드의 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해당 텍스트 필드의 속성입니다.

보기 컨트롤러를 다음과 같이 확장합니다.

class MyViewController: UIViewController, UITextFieldDelegate

보기 DidLoad 기능은 다음과 같이 텍스트 필드로 확장됩니다.

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
}

그러면 사용자가 10진수만 입력할 수 있습니다.

스위프트 4 + 숫자만 허용하고 구분자 하나만 허용합니다.

번호포맷 사용

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

간단한 해결 방법은 다음과 같습니다. "변경된 편집" 이벤트를 컨트롤러의 이 메서드에 연결해야 합니다.

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

먼저 자신의 클래스와 함께 UITextFieldDelegate 클래스를 상속해야 합니다.

class ViewController: UIViewController, UITextFieldDelegate {

두 번째로 IBOUTLET 추가

@IBOutlet weak var firstName: UITextField!

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

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


      }
  }

이러한 솔루션의 대부분은 효과가 있겠지만, 일부 지역화에서는 소수점이 ""이 아닌 ""으로 구분된다는 점에 유의해야 합니다.

이것을 하는 더 깔끔한 방법은

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
}

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

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

위의 코드는 swift 3에서 작동하고 있습니다.
NS 문자 집합. 10진수
또한 문자만 사용합니다.
NS 문자 집합.편지
그리고 대문자,소문자, 알파벳 숫자, 공백이 동일한 코드로 사용되거나 링크 참조

보다 깨끗한 해결책은 다음과 같습니다.

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

소수점에 대해서는 추가하기만 하면 됩니다..,123456789.

키보드 설정유형 속성 : - 번호 패드 텍스트 필드 위임자 코드 아래에 기록하십시오.

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

    if textField.text?.count == 0 && string == "0" {
        return false
    }
    return string == string.filter("0123456789".contains)
}

숫자는 0부터 시작해서 숫자 +ve를 입력하면 안 됩니다.

//이 중 instead은 키보드를 숫자로 간단히 변경할 수 있습니다.

yourtextfield.keyboardType = UIKeyboardType.numberPad
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

  }

답이 부족한 것처럼, 여기 제 것이 있습니다.소수점 구분자에 허용되는 모든 예는 현지화, 백스페이스 또는 복사/붙여넣기에서 결함이 있다고 생각합니다.

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

이 기능을 "제출" 또는 "저장" 방법으로 설정합니다.

다음은 제가 스위프트 3.0에서 사용한 코드로 H씨의 코드를 각색한 것입니다.차이점은 다음과 같습니다.

a) 스위프트 3.0에서 Delegate 함수 선언이 변경되었습니다.여기에 새 선언

b) NS 문자 집합 선언이 변경되었습니다.

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

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

스위프트 4로 작성된 코드인데 스위프트 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
}

소수 또는 음수를 허용하지 않으려면 토우 변수를 다음 줄로 대체해야 합니다.

let allowDecimal = ""
let allowSign = ""

일부 문자 허용

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

이 버전은 "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
        }
    }
}

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

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
}

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

반응형