Максимальна довжина UITextField


120

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

Єдине, що я можу зробити - це скасувати операцію (видалити всі символи разом).

Хтось знає, як не блокувати клавіатуру (щоб я не могла додавати інші літери / символи / цифри, але можу використовувати зворотний простір)?

Відповіді:


294

За допомогою 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«S 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
    }

}

Ви просто ввели цей код у свій клас контролера перегляду? Або мені потрібно встановити зв’язки?
Ісаак Вассерман

Якщо комусь потрібно поставити якусь умову .. ви можете зробити так ... if (textField .isEqual (mobileNumberTextfield)) {guard let text = textField.text else {return true} let newLength = text.characters.count + string.characters.count - range.length return newLength <= limitLength; } повернути правду;
Нарасимха Налламсетті

5
Для Swift 4 text.characters.countзастаріле використанняtext.count
Мохамед Салах

47

Я роблю це так:

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

Код працює для мене. Але я працюю з раскадровкой. У розділ "Розгортка" я додаю дію для текстового поля в контролері перегляду під час редагування .


1
countElements було змінено на підрахунок у Swift 2, але зміна працює для мене!
Іван

1
Дякую, ви можете зараз використовувати textField.text? .Characters.count, оскільки countElements були змінені.
Анібал Р.

1
Tks, він прекрасно спрацював із цією зміною: countElements (textField.text!) У Swift 2 є: textField.text? .Characters.count
kha

33

Оновлення для 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
}

15

Додати більш детальну інформацію з відповіді @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()
    }
}

1
count (textField.text!) видає помилку. Ви повинні використовувати textField.text! .Characters.count
Regis St-Gelais

1
Дякую @ RegisSt-Gelais, це вже стара відповідь, я оновив її зараз
Sruit A.Suk

11

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

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

невелика зміна для IOS 9


8

Швидкий 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

ви можете розширити UITextField і додати @IBInspectableоб’єкт для обробки:

SWIFT 5

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)
        }
    }
    @objc func fix(textField: UITextField) {
        if let t = textField.text {
            textField.text = String(t.prefix(maxLength))
        }
    }
}

а після цього визначте його за атрибутом інспектора

введіть тут опис зображення

Див. Оригінал відповіді Swift 4


2
Гарний, чистий код. Але чомусь це спричиняє дивну поведінку редагування, коли ви використовуєте емоджи. Курсор пропускає до кінця рядка щоразу, коли ви намагаєтесь редагувати.
Phontaine Judd

5

Якщо ви хочете замінити останній лист:

let maxLength = 10

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

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

    return true
}

4

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


3

Ви можете використовувати в swift 5 або swift 4, як зображення виглядають нижче введіть тут опис зображення

  1. Додати текстове поле у ​​контролер перегляду
  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


1

Остерігайтеся скасування помилки для UITextField, згаданого в цій публікації: Встановіть максимальну довжину символу UITextField

ось як це швидко виправити

if(range.length + range.location > count(textField.text)) {
        return false;
}

Якщо ви хочете підтримати смайли та таке використання: if (range.length + range.location> count (textField.text.utf16)) {return false; }
AlexD

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

1
Мені подобається розширення Toast UIView :)
Regis St-Gelais

1

Я використовую цей протокол / розширення в одному зі своїх додатків, і це трохи читабельніше. Мені подобається, як він розпізнає зворотні простори і явно повідомляє вам, коли персонаж є заднім простором.

Деякі речі, які слід врахувати:

1.Що б не реалізував це розширення протоколу, потрібно вказати обмеження символів. Зазвичай це буде ваш ViewController, але ви можете реалізувати обмеження символів як обчислене властивість та повернути щось інше, наприклад обмеження символів на одній із ваших моделей.

2. Вам потрібно буде зателефонувати до цього методу всередині методу делегування wordChangeCharactersInRange вашого текстового поля. Інакше ви не зможете заблокувати введення тексту, повернувши помилку тощо.

3. Ви, ймовірно, захочете дозволити резервні символи наскрізь. Тому я додав додаткову функцію для виявлення зворотних просторів. Ваш метод shouldChangeCharacters може перевірити це та повернути 'true' на початку, щоб ви завжди дозволяли мати відстані.

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, яке показує, як далеко ви перевищили ліміт символів.

Характер Обмежена рамка на Github


1

Оскільки делегати мають відношення 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)

        }

0

Я використовую це;

Обмежте 3 char

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

        if let txt = textField.text {
            let currentText = txt + string
            if currentText.count > 3 {
                return false
            }
            return true
        }
        return true
    }

0

Швидкий 5

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        let MAX_LENGTH = 4
        let updatedString = (textField.text! as NSString).replacingCharacters(in: range, with: string)
        return updatedString.count <= MAX_LENGTH
    }

-3

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

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

5
Ваш код неправильний. 1. Ви повинні оголосити свою константу або змінну з let або var у Swift (не NSUInteger). 2. textField.text і рядок мають тип String. Length не є властивістю / методом String in Swift.
Imanou Petit
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.