Максимальная длина UITextField

Когда я пробовал Как установить максимальное количество символов, которые можно ввести в UITextField с помощью быстрого?, я увидел, что если я использую все 10 символов, я тоже не могу стереть символ.

Единственное, что я могу сделать, это отменить операцию (удалить все символы вместе).

Кто-нибудь знает, как не блокировать клавиатуру (чтобы я не мог добавлять другие буквы/символы/цифры, но я могу использовать backspace)?

Ответ 1

В Swift 5 и iOS 12 попробуйте следующую реализацию метода textField(_:shouldChangeCharactersIn:replacementString:) который является частью протокола UITextFieldDelegate:

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
    }
    let substringToReplace = textFieldText[rangeOfTextToReplace]
    let count = textFieldText.count - substringToReplace.count + string.count
    return count <= 10
}
  • Наиболее важной частью этого кода является преобразование range (NSRange) в rangeOfTextToReplace (Range<String.Index>). Посмотрите этот видеоурок, чтобы понять, почему это преобразование важно.
  • Чтобы этот код работал правильно, вы также должны установить значение textField smartInsertDeleteType в UITextSmartInsertDeleteType.no. Это предотвратит возможную вставку (нежелательного) дополнительного пространства при выполнении операции вставки.

Полный пример кода ниже показывает, как реализовать textField(_:shouldChangeCharactersIn:replacementString:) в UIViewController:

import UIKit

class ViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet var textField: UITextField! // Link this to a UITextField in Storyboard

    override func viewDidLoad() {
        super.viewDidLoad()

        textField.smartInsertDeleteType = UITextSmartInsertDeleteType.no
        textField.delegate = self
    }

    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
        }
        let substringToReplace = textFieldText[rangeOfTextToReplace]
        let count = textFieldText.count - substringToReplace.count + string.count
        return count <= 10
    }

}

Ответ 2

Я делаю это так:

func checkMaxLength(textField: UITextField!, maxLength: Int) {
    if (countElements(textField.text!) > maxLength) {
        textField.deleteBackward()
    }
}

Код работает для меня. Но я работаю с раскадрой. В Storyboard я добавляю действие для текстового поля в контроллере представления в редактировании изменено.

Ответ 3

Обновление для Swift 4

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

Ответ 4

Добавить более подробно из ответа @Martin

// linked your button here
@IBAction func mobileTFChanged(sender: AnyObject) {
    checkMaxLength(sender as! UITextField, maxLength: 10)
}

// linked your button here
@IBAction func citizenTFChanged(sender: AnyObject) {
    checkMaxLength(sender as! UITextField, maxLength: 13)
}

func checkMaxLength(textField: UITextField!, maxLength: Int) {
    // swift 1.0
    //if (count(textField.text!) > maxLength) {
    //    textField.deleteBackward()
    //}
    // swift 2.0
    if (textField.text!.characters.count > maxLength) {
        textField.deleteBackward()
    }
}

Ответ 5

В Swift 4

10 символов ограничивают текстовое поле и позволяют удалить (возврат)

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        if textField ==  userNameFTF{
            let char = string.cString(using: String.Encoding.utf8)
            let isBackSpace = strcmp(char, "\\b")
            if isBackSpace == -92 {
                return true
            }
            return textField.text!.count <= 9
        }
        return true
    }

Ответ 6

func checkMaxLength(textField: UITextField!, maxLength: Int) {
        if (textField.text!.characters.count > maxLength) {
            textField.deleteBackward()
        }
}

небольшое изменение для IOS 9

Ответ 7

Swift 3

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

            let nsString = NSString(string: textField.text!)
            let newText = nsString.replacingCharacters(in: range, with: string)
            return  newText.characters.count <= limitCount
    }

Ответ 8

Если вы хотите перезаписать последнюю букву:

let maxLength = 10

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

    if range.location > maxLength - 1 {
        textField.text?.removeLast()
    }

    return true
}

Ответ 9

Я разместил решение с помощью IBInspectable, поэтому вы можете изменить максимальное значение длины как в построителе интерфейса, так и программно. Проверьте здесь

Ответ 11

Here is my version of code. Hope it helps!

    func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
        let invalidCharacters = NSCharacterSet(charactersInString: "0123456789").invertedSet

        if let range = string.rangeOfCharacterFromSet(invalidCharacters, options: nil, range:Range<String.Index>(start: string.startIndex, end: string.endIndex))
        {
            return false
        }

        if (count(textField.text) > 10  && range.length == 0)
        {
            self.view.makeToast(message: "Amount entry is limited to ten digits", duration: 0.5, position: HRToastPositionCenter)
            return false
        }
        else
        {

        }

        return true
    }

Ответ 12

Я использую этот протокол/расширение в одном из моих приложений, и он немного читаем. Мне нравится, как он распознает обратные пространства и явно сообщает вам, когда символ является backspace.

Некоторые вещи, которые следует учитывать:

1. В любом случае это расширение протокола должно указывать ограничение символа. Обычно это будет ваш ViewController, но вы можете реализовать ограничение символа как вычисленное свойство и вернуть что-то еще, например лимит символов на одной из ваших моделей.

2. Вам нужно будет вызвать этот метод внутри вашего текстового поля shouldChangeCharactersInRange метод делегата. В противном случае вы не сможете заблокировать ввод текста, вернув false и т.д.

3. Вероятно, вы захотите разрешить обратные символы.. Поэтому я добавил дополнительную функцию для обнаружения обратных пространств. Ваш метод shouldChangeCharacters может проверить это и вернуть "истина" на раннем этапе, чтобы вы всегда разрешали backspaces.

protocol TextEntryCharacterLimited{
    var characterLimit:Int { get } 
}

extension TextEntryCharacterLimited{

    func charactersInTextField(textField:UITextField, willNotExceedCharacterLimitWithReplacementString string:String, range:NSRange) -> Bool{

        let startingLength = textField.text?.characters.count ?? 0
        let lengthToAdd = string.characters.count
        let lengthToReplace = range.length

        let newLength = startingLength + lengthToAdd - lengthToReplace

        return newLength <= characterLimit

    }

    func stringIsBackspaceWith(string:String, inRange range:NSRange) -> Bool{
        if range.length == 1 && string.characters.count == 0 { return true }
        return false
    }

}

Если кто-то из вас интересуется, у меня есть репозиторий Github, где я взял некоторые из этих правил поведения персонажа и поместил его в iOS. Там протокол, который вы можете реализовать, чтобы отобразить лимит символов на Twitter, показывает, насколько вы прошли выше лимита символов.

CharacterLimited Framework в Github

Ответ 13

Поскольку делегаты являются отношениями 1 к 1, и я могу использовать его в другом месте по другим причинам, мне нравится ограничивать длину текстового поля, добавляя этот код в свою установку:

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)!
        setup()
    }

    required override init(frame: CGRect) {
        super.init(frame: frame)
        setup()
    }

    func setup() {

        // your setup...

        setMaxLength()
    }

    let maxLength = 10

    private func setMaxLength() {
            addTarget(self, action: #selector(textfieldChanged(_:)), for: UIControlEvents.editingChanged)
        }

        @objc private func textfieldChanged(_ textField: UITextField) {
            guard let text = text else { return }
            let trimmed = text.characters.prefix(maxLength)
            self.text = String(trimmed)

        }

Ответ 14

Вы можете использовать в Swift 5 или Swift 4, как изображение выглядит как ниже enter image description here

  1. Добавить textField в View Controller
  2. Подключиться к тексту в ViewController
  3. добавить код в представление ViewController

     class ViewController: UIViewController , UITextFieldDelegate {
    
      @IBOutlet weak var txtName: UITextField!
    
      var maxLen:Int = 8;
    
     override func viewDidLoad() {
        super.viewDidLoad()
    
        txtName.delegate = self
       }
    
     func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    
         if(textField == txtName){
            let currentText = textField.text! + string
            return currentText.count <= maxLen
         }
    
         return true;
       }
    }
    

Вы можете скачать полную исходную форму GitHub: https://github.com/enamul95/TextFieldMaxLen

Ответ 15

Вам нужно проверить, будет ли существующая строка плюс вход больше 10.

   func textField(textField: UITextField!,shouldChangeCharactersInRange range: NSRange,    replacementString string: String!) -> Bool {
      NSUInteger newLength = textField.text.length + string.length - range.length;
      return !(newLength > 10)
   }