programing

Swift에서 UI 텍스트 필드의 최대 문자 길이 설정

lastmoon 2023. 9. 4. 20:34
반응형

Swift에서 UI 텍스트 필드의 최대 문자 길이 설정

이에 대한 다른 주제가 있다는 것은 알지만, 어떻게 구현해야 할지 모르겠습니다.

UI 텍스트 필드를 5자로 제한하려고 합니다.

가적영숫자급,-,.,그리고._.

이 코드를 본 적이 있습니다.

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange,
                       replacementString string: String) -> Bool
{
    let maxLength = 4
    let currentString: NSString = textField.text
    let newString: NSString =
             currentString.stringByReplacingCharactersInRange(range, withString: string)
    return newString.length <= maxLength
}

그리고.

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

    let length = count(textField.text.utf16) + count(string.utf16) - range.length
    return length <= 10
}

실제로 구현하려면 어떻게 해야 합니까?어떤 "텍스트 필드"를 사용자 지정인 UITextField로 교체해야 합니까?

  1. 는 뷰컨트롤러가합야니다준해수다음을에 따라야 .UITextFieldDelegate아래와 같이:

    class MyViewController: UIViewController, UITextFieldDelegate {
    
    }
    
  2. 필드의 합니다.myTextField.delegate = self

  3. 보기 컨트롤러에서 메소드를 구현합니다.

    textField(_:shouldChangeCharactersInRange:replacementString:)
    

모두 함께:

class MyViewController: UIViewController, UITextFieldDelegate  // Set delegate to class

@IBOutlet var mytextField: UITextField             //  textfield variable

override func viewDidLoad() {
    super.viewDidLoad()
    mytextField.delegate = self                  // set delegate
}


func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange,
                       replacementString string: String) -> Bool
{
    let maxLength = 4
    let currentString: NSString = textField.text
    let newString: NSString =  currentString.stringByReplacingCharactersInRange(range, withString: string)

    return newString.length <= maxLength
}

스위프트 4용

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    let maxLength = 1
    let currentString: NSString = (textField.text ?? "") as NSString
    let newString: NSString =  currentString.replacingCharacters(in: range, with: string) as NSString

    return newString.length <= maxLength
}

스위프트 5용

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    let maxLength = 1
    let currentString = (textField.text ?? "") as NSString
    let newString = currentString.replacingCharacters(in: range, with: string)

    return newString.count <= maxLength
}

지정된 문자 집합만 지정된 텍스트 필드에 입력할 수 있음

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

    if mytextField == textField {
        if count(string) > 0 {
            let disallowedCharacterSet = NSCharacterSet(charactersInString: "0123456789.-").invertedSet
            let replacementStringIsLegal = string.rangeOfCharacterFromSet(disallowedCharacterSet) == nil
            result = replacementStringIsLegal
        }
    }

    return result
}

최대 길이의 숫자 입력만 사용하는 iOS 텍스트 필드를 프로그래밍하는 방법

모던 스위프트

온라인 예제 코드의 대부분은 매우 구식입니다.

프로젝트의 모든 Swift 파일(예: "Handy.swift")에 다음을 붙여넣습니다.

이것은 iOS에서 가장 어리석은 문제 중 하나를 해결합니다.

enter image description here

에 이제텍필에가 됩니다..maxLength.

앱이 실행되는 동안 스토리보드나 코드에 해당 값을 설정해도 괜찮습니다.

// Handy.swift

import UIKit
private var __maxLengths = [UITextField: Int]()
extension UITextField {
    @IBInspectable var maxLength: Int {
        get {
            guard let l = __maxLengths[self] else {
               return 150 // (global default-limit. or just, Int.max)
            }
            return l
        }
        set {
            __maxLengths[self] = newValue
            addTarget(self, action: #selector(fix), for: .editingChanged)
        }
    }
    func fix(textField: UITextField) {
        let t = textField.text
        textField.text = t?.prefix(maxLength).string
    }
}

그렇게 간단하다.

더 단순한 일회성 버전은...

위의 내용은 전체 프로젝트의 모든 텍스트 필드를 수정합니다.

특정 텍스트 필드 하나를 단순히 "4"로 제한하고 싶다면, 그게 바로...

class PinCodeEntry: UITextField {
    
    override func didMoveToSuperview() {
        
        super.didMoveToSuperview()
        addTarget(self, action: #selector(fixMe), for: .editingChanged)
    }
    
    @objc private func fixMe() { text = text?.prefix(4) }
}

그게 다야.

(UITextView, https://stackoverflow.com/a/42333832/294884 와 관련하여 매우 유용한 유사한 팁이 있습니다.)

Swift 4에서는 다음을 사용합니다.

public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    return range.location < 10
}

Steven Schmatz와 동일한 방식으로 Swift 3.0을 사용했습니다.

//max Length
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange,
               replacementString string: String) -> Bool
{
    let maxLength = 4
    let currentString: NSString = textField.text! as NSString
    let newString: NSString = currentString.replacingCharacters(in: range, with: string) as NSString
    return newString.length <= maxLength
}

대리인을 사용하지 않는 간단한 솔루션:

TEXT_FIELD.addTarget(self, action: #selector(editingChanged(sender:)), for: .editingChanged)


@objc private func editingChanged(sender: UITextField) {

        if let text = sender.text, text.count >= MAX_LENGHT {
            sender.text = String(text.dropLast(text.count - MAX_LENGHT))
            return
        }
}

Swift 5의 경우:

최대 문자 길이를 설정하려면 한 줄만 작성하면 됩니다.

 self.textField.maxLength = 10

자세한 내용은 UITextField의 최대 문자 제한허용 문자 Swift를 참조하십시오. (또한 인정됨)

이것은 연장이 더 편리할 것 같습니다.여기에서 전체 답변을 확인하십시오.

private var maxLengths = [UITextField: Int]()

// 2
extension UITextField {

  // 3
  @IBInspectable var maxLength: Int {
    get {
      // 4
      guard let length = maxLengths[self] else {
        return Int.max
      }
      return length
    }
    set {
      maxLengths[self] = newValue
      // 5
      addTarget(
        self,
        action: #selector(limitLength),
        forControlEvents: UIControlEvents.EditingChanged
      )
    }
  }

  func limitLength(textField: UITextField) {
    // 6
    guard let prospectiveText = textField.text
      where prospectiveText.characters.count > maxLength else {
        return
    }

    let selection = selectedTextRange
    // 7
    text = prospectiveText.substringWithRange(
      Range<String.Index>(prospectiveText.startIndex ..< prospectiveText.startIndex.advancedBy(maxLength))
    )
    selectedTextRange = selection
  }

}

4 마이 스위프트 4 ㅠㅠㅠshouldChangeCharactersIn

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

    guard let preText = textField.text as NSString?,
        preText.replacingCharacters(in: range, with: string).count <= MAX_TEXT_LENGTH else {
        return false
    }

    return true
}

이전에 게시된 다른 솔루션은 텍스트 필드 맵으로 인해 유지 주기를 생성합니다. 다가게, 그그.maxLength 속은인대이신설않정지은합경니다우어야되성위인 대신 설정하지 않으면 이어야 합니다.Int.max변경되면 번 됩니다.

여기 메모리 누수를 방지하고 다른 수정 사항을 방지하기 위한 약한 맵을 가진 Swift4용 업데이트된 솔루션이 있습니다.

private var maxLengths = NSMapTable<UITextField, NSNumber>(keyOptions: NSPointerFunctions.Options.weakMemory, valueOptions: NSPointerFunctions.Options.strongMemory)

extension UITextField {

    var maxLength: Int? {
        get {
            return maxLengths.object(forKey: self)?.intValue
        }
        set {
            removeTarget(self, action: #selector(limitLength), for: .editingChanged)
            if let newValue = newValue {
                maxLengths.setObject(NSNumber(value: newValue), forKey: self)
                addTarget(self, action: #selector(limitLength), for: .editingChanged)
            } else {
                maxLengths.removeObject(forKey: self)
            }
        }
    }

    @IBInspectable var maxLengthInspectable: Int {
        get {
            return maxLength ?? Int.max
        }
        set {
            maxLength = newValue
        }
    }

    @objc private func limitLength(_ textField: UITextField) {
        guard let maxLength = maxLength, let prospectiveText = textField.text, prospectiveText.count > maxLength else {
            return
        }
        let selection = selectedTextRange
        text = String(prospectiveText[..<prospectiveText.index(from: maxLength)])
        selectedTextRange = selection
    }
}

저는 @Frouo를 바탕으로 보충 답변을 드립니다.저는 그의 대답이 가장 아름다운 방법이라고 생각합니다.우리가 재사용할 수 있는 공통 제어장치이기 때문입니다.그리고 여기에는 누수 문제가 없습니다.

private var kAssociationKeyMaxLength: Int = 0

extension UITextField {

    @IBInspectable var maxLength: Int {
        get {
            if let length = objc_getAssociatedObject(self, &kAssociationKeyMaxLength) as? Int {
                return length
            } else {
                return Int.max
            }
        }
        set {
            objc_setAssociatedObject(self, &kAssociationKeyMaxLength, newValue, .OBJC_ASSOCIATION_RETAIN)
            self.addTarget(self, action: #selector(checkMaxLength), for: .editingChanged)
        }
    }

    // The method is used to cancel the check when using
    // the Chinese Pinyin input method.
    // Becuase the alphabet also appears in the textfield
    // when inputting, we should cancel the check.
    func isInputMethod() -> Bool {
        if let positionRange = self.markedTextRange {
            if let _ = self.position(from: positionRange.start, offset: 0) {
                return true
            }
        }
        return false
    }


    func checkMaxLength(textField: UITextField) {

        guard !self.isInputMethod(), let prospectiveText = self.text,
            prospectiveText.count > maxLength
        else {
            return
        }

        let selection = selectedTextRange
        let maxCharIndex = prospectiveText.index(prospectiveText.startIndex, offsetBy: maxLength)
        text = prospectiveText.substring(to: maxCharIndex)
        selectedTextRange = selection
    }

}

문자열의 문자 수를 확인하기만 하면 됩니다.

  1. 컨트롤러를 볼 대리인을 추가하고 대리인을 할당합니다.

    class YorsClassName : UITextFieldDelegate {
    
    }
    
  2. 텍스트 필드에 허용되는 문자 수 확인

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        if textField.text?.count == 1 {
            return false
        }
        return true
    }
    

참고: 여기서는 textField에 허용되는 문자만 확인했습니다.

Swift 4에서 텍스트 차단 후 텍스트 필드 제한 문자

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


    if textField == self.txtDescription {
        let maxLength = 200
        let currentString: NSString = textField.text! as NSString
        let newString: NSString = currentString.replacingCharacters(in: range, with: string) as NSString
        return newString.length <= maxLength
    }

    return true


}

알라딘의 대답에 덧붙일 말이 있습니다.

  1. 뷰 컨트롤러가 다음을 준수해야 합니다.UITextFieldDelegate

     class MyViewController: UIViewController, UITextViewDelegate {
    
     }
    
  2. 텍스트 필드의 대리자를 설정합니다.

    위임자를 설정하려면 텍스트 필드에서 스토리보드의 뷰 컨트롤러로 드래그를 제어할 수 있습니다.코드로 설정하는 것보다 이것이 더 낫다고 생각합니다.

  3. 보기 컨트롤러에서 메소드를 구현합니다.

     textField(_:shouldChangeCharactersInRange:replacementString:)
    

패티의 답변에 대한 업데이트:

extension UITextField {

    // Runtime key
    private struct AssociatedKeys {
        // Maximum length key
        static var maxlength: UInt8 = 0
        // Temporary string key
        static var tempString: UInt8 = 0
    }

    // Limit the maximum input length of the textfiled
    @IBInspectable var maxLength: Int {
        get {
            return objc_getAssociatedObject(self, &AssociatedKeys.maxlength) as? Int ?? 0
        }
        set {
            objc_setAssociatedObject(self, &AssociatedKeys.maxlength, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            addTarget(self, action: #selector(handleEditingChanged(textField:)), for: .editingChanged)
        }
    }

    // Temporary string
    private var tempString: String? {
        get {
            return objc_getAssociatedObject(self, &AssociatedKeys.tempString) as? String
        }
        set {
            objc_setAssociatedObject(self, &AssociatedKeys.tempString, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }

    // When the text changes, process the amount of text in the input
    // box so that its length is within the controllable range.
    @objc private func handleEditingChanged(textField: UITextField) {

        // Special processing for the Chinese input method
        guard markedTextRange == nil else { return }

        if textField.text?.count == maxLength {

            // Set lastQualifiedString where text length == maximum length
            tempString = textField.text
        } else if textField.text?.count ?? 0 < maxLength {

            // Clear lastQualifiedString when text length > maxlength
            tempString = nil
        }

        // Keep the current text range in arcgives
        let archivesEditRange: UITextRange?

        if textField.text?.count ?? 0 > maxLength {

            // If text length > maximum length, remove last range and to move to -1 postion.
            let position = textField.position(from: safeTextPosition(selectedTextRange?.start), offset: -1) ?? textField.endOfDocument
            archivesEditRange = textField.textRange(from: safeTextPosition(position), to: safeTextPosition(position))
        } else {

            // Just set current select text range
            archivesEditRange = selectedTextRange
        }

        // Main handle string maximum length
        textField.text = tempString ?? String((textField.text ?? "").prefix(maxLength))

        // Last configuration edit text range
        textField.selectedTextRange = archivesEditRange
    }

    // Get safe textPosition
    private func safeTextPosition(_ optionlTextPosition: UITextPosition?) -> UITextPosition {

        /* beginningOfDocument -> The end of the the text document. */
        return optionlTextPosition ?? endOfDocument
    }
}
  1. 텍스트 필드의 대리자를 설정합니다.

     textField.delegate = self
    
  2. 보기 컨트롤러에서 메소드를 구현합니다.

     // MARK: Text field delegate
    
     extension ViewController: UITextFieldDelegate {
         func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
             return range.location < maxLength (maxLength can be any maximum length you can define)
         }
     }
    

불필요한 문자열 조작을 방지하는 Swift 3.2+ 대안이 있습니다.이 경우 최대 길이는 10입니다.

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    let text = textField.text ?? ""

    return text.count - range.length + string.count <= 10
}

이 대답은 Swift 4를 위한 것이며 백스페이스가 통과할 수 있도록 하는 기능으로 매우 간단합니다.

func textField(_ textField: UITextField,
               shouldChangeCharactersIn range: NSRange,
               replacementString string: String) -> Bool {
    return textField.text!.count < 10 || string == ""
}

이것은 Swift 4에서 작동합니다.

1단계: UITextField 딜러 설정

class SignUPViewController: UIViewController , UITextFieldDelegate {

   @IBOutlet weak var userMobileNoTextFiled: UITextField!

    override func viewDidLoad() {
        super.viewDidLoad()

2단계: 딜러를 설정

        userMobileNoTextFiled.delegate = self                  // Set delegate
   }

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    //        guard let text = userMobileNoTextFiled.text else { return true }
    //        let newLength = text.count + string.count - range.length
    //        return newLength <= 10
    //    }

3단계: 기능 호출

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        let maxLength = 10          // Set your need
        let currentString: NSString = textField.text! as NSString
        let newString: NSString =
            currentString.replacingCharacters(in: range, with: string) as NSString
        return newString.length <= maxLength
    }
}

저는 이 단계들을 사용합니다.먼저 view didload에서 대리자 텍스트 필드를 설정합니다.

override func viewDidLoad() {
    super.viewDidLoad()

    textfield.delegate = self
}

그런 다음 UITextFieldDelegate를 포함한 후 CharactersIn을 변경해야 합니다.

extension viewController: UITextFieldDelegate {
    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        let newLength = (textField.text?.utf16.count)! + string.utf16.count - range.length
        if newLength <= 8 {
            return true
        }
        else {
            return false
        }
    }
}

만약을 대비해서, 끈에 적용하기 전에 범위 크기를 지키는 것을 잊지 마세요.그렇지 않으면 사용자가 다음 작업을 수행할 경우 충돌이 발생합니다.

  • 최대 길이 텍스트 입력
  • 무언가를 삽입합니다(길이 제한으로 인해 아무것도 삽입되지 않지만 iOS는 이에 대해 알지 못합니다).
  • 삽입 실행 취소(범위가 실제 문자열 크기보다 크기 때문에 충돌이 발생함)

또한, iOS 13을 사용하는 사용자는 실수로 제스처에 의해 이것을 트리거할 수 있습니다.

당신의 프로젝트에 이것을 추가하는 것을 제안합니다.

extension String {
    func replace(with text: String, in range: NSRange) -> String? {
        // NOTE: NSString conversion is necessary to operate in the same symbol steps
        // Otherwise, you may not be able to delete an emoji, for example
        let current = NSString(string: self)
        guard range.location + range.length <= current.length else { return nil }
        return current.replacingCharacters(in: range, with: text)
    }
}

다음과 같이 사용합니다.

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    guard let newText = textView.text.replace(with: text, in: range) else { return false }
    return newText.count < maxNumberOfCharacters
    // NOTE: You may wanna trim the new text instead,
    // so the user will able to shove his long text at least partially
}

그렇지 않으면 앱에서 지속적으로 충돌이 발생할 수 있습니다.

한 페이지에 다양한 길이 검사가 있는 textField가 여러 개 있는 경우 쉽고 간단한 해결책을 찾았습니다.

class MultipleTextField: UIViewController {

    let MAX_LENGTH_TEXTFIELD_A = 10
    let MAX_LENGTH_TEXTFIELD_B = 11

    lazy var textFieldA: UITextField = {
        let textField = UITextField()
        textField.tag = MAX_LENGTH_TEXTFIELD_A
        textField.delegate = self
        return textField
    }()
    lazy var textFieldB: UITextField = {
        let textField = UITextField()
        textField.tag = MAX_LENGTH_TEXTFIELD_B
        textField.delegate = self
        return textField
    }()
}

extension MultipleTextField: UITextFieldDelegate {
    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        return (range.location < textField.tag) && (string.count < textField.tag)
    }
}
lazy var textField: UITextField = {
  let textField = UITextField()
  textField.addTarget(self, #selector(handleOnEditing), for .editingChanged)
  return textField
}()

//ViewDidLoad textField.delegate = self에서 Delegate

@objc func handleOnEditing() {
   let text = textField.text ?? ""
   let limit = 10
   textField.text = String(text.prefix(limit))
}

이러한 답변을 스크롤할 때 제가 찾던 답변을 완전히 이해할 수 없었습니다(그러나 저였을 수도 있습니다).한 보기 내에서 두 개의 텍스트 필드에 최대 문자를 설정하려고 합니다(다른 텍스트 필드를 확장하면 더 많은 문자를 설정할 수 있음).제가 찾은 해결책 중 가장 깨끗한 것은 확장이었습니다.여기 코드가 있습니다. VC와 textField를 사용하여 Place things를 조정하십시오.

extension PlaceYourViewControllerHere: UITextFieldDelegate {

private var maxCharacters: Int = 24

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    guard let textFieldText = textField.text,
            let rangeOfTextToReplace = Range(range, in: textFieldText) else {
        return false
    }
    if textField == placeFirstTextfieldHere { maxCharacters = 64 } else { maxCharacters = 255 }
    let substringToReplace = textFieldText[rangeOfTextToReplace]
    let count = textFieldText.count - substringToReplace.count + string.count
    return count <= maxCharacters
    }

}

편집: textField에서 대리자를 설정하는 것을 잊지 마십시오.

        textField.delegate = self

언급URL : https://stackoverflow.com/questions/31363216/set-the-maximum-character-length-of-a-uitextfield-in-swift

반응형