Установите максимальную длину символа UITextField

452

Как установить максимальное количество символов в UITextField на iPhone SDK при загрузке UIView?

Теги:
uitextfield
cocoa-touch

42 ответа

944
Лучший ответ

Хотя класс UITextField не имеет свойства max length, относительно просто получить эту функцию, установив delegate текстового поля и реализовав следующий метод делегата:

Objective-C

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    // Prevent crashing undo bug – see note below.
    if(range.length + range.location > textField.text.length)
    {
        return NO;
    }

    NSUInteger newLength = [textField.text length] + [string length] - range.length;
    return newLength <= 25;
}

стриж

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

    let currentCharacterCount = textField.text?.count ?? 0
    if range.length + range.location > currentCharacterCount {
        return false
    }
    let newLength = currentCharacterCount + string.count - range.length
    return newLength <= 25
}

Перед изменением текстового поля UITextField спрашивает делегата, должен ли быть изменен указанный текст. На этом этапе текстовое поле не изменилось, поэтому мы берем текущую длину и длину вставляемой строки (либо путем вставки скопированного текста, либо путем ввода одного символа с помощью клавиатуры), за вычетом длины диапазона. Если это значение слишком длинное (более 25 символов в этом примере), верните NO чтобы запретить изменение.

При вводе одного символа в конце текстового поля range.location будет текущей длиной поля, а range.length будет 0, потому что мы ничего не заменяем/не range.length. Вставка в середину текстового поля означает просто другое расположение range.location, а вставка нескольких символов означает, что string содержит более одного символа.

Удаление отдельных символов или вырезание нескольких символов определяется range с ненулевой длиной и пустой строкой. Замена - это просто удаление диапазона с непустой строкой.

Примечание о сбое "отменить" ошибку

Как уже упоминалось в комментариях, в UITextField есть ошибка, которая может привести к сбою.

Если вы вставляете в поле, но вставка предотвращается вашей реализацией проверки, операция вставки все еще записывается в буфер отмены приложения. Если вы затем UITextField отмену (встряхивая устройство и подтверждая отмену), UITextField попытается заменить строку, которую он считает вставленной в себя, пустой строкой. Это приведет к сбою, потому что он никогда не вставлял строку в себя. Он попытается заменить часть строки, которая не существует.

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

Swift 3.0 с копией и вставкой работает нормально.

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
        let str = (textView.text + text)
        if str.characters.count <= 10 {
            return true
        }
        textView.text = str.substring(to: str.index(str.startIndex, offsetBy: 10))
        return false
    }

Надеюсь, что это полезно для вас.

  • 0
    Прекрасно работает ... Как для добавления / удаления.
  • 0
    Как я могу установить это только для одного UITextView на моем экране? Когда я добавляю его в свой класс, он применяется ко всем текстовым представлениям.
Показать ещё 26 комментариев
54

Спасибо, август! (Сообщение)

Это код, с которым я закончил работу:

#define MAX_LENGTH 20

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    if (textField.text.length >= MAX_LENGTH && range.length == 0)
    {
        return NO; // return NO to not change text
    }
    else
    {return YES;}
}
  • 19
    К сожалению, это решение не может остановить копирование и вставку пользователей в текстовое поле, что позволяет им обойти ограничение. Ответ Sickpea справляется с этой ситуацией правильно.
  • 5
    Что с людьми, имеющими заявление if, чтобы возвратить НЕТ или ДА? Попробуйте это: return! (TextField.text.length> = MAX_LENGTH && range.length == 0);
Показать ещё 1 комментарий
47

Swift 4

import UIKit

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)
            addTarget(self, action: #selector(checkMaxLength), for: .editingChanged)
        }
    }

    @objc func checkMaxLength(textField: UITextField) {
        guard let prospectiveText = self.text,
            prospectiveText.count > maxLength
            else {
                return
        }

        let selection = selectedTextRange

        let indexEndOfText = prospectiveText.index(prospectiveText.startIndex, offsetBy: maxLength)
        let substring = prospectiveText[..<indexEndOfText]
        text = String(substring)

        selectedTextRange = selection
    }
}

Редактировать: исправлена проблема утечки памяти.

Изображение 5338

  • 0
    Отличная идея Frouo! Я расширил его в своем ответе, чтобы переместить усечение maxLength в расширение String, чтобы его также можно было использовать для таких вещей, как экземпляры UITextView, и добавить вспомогательную функцию, чтобы использовать преимущества этих расширений String в расширении UITextField.
  • 1
    Разве эта глобальная переменная не создает утечек памяти, удерживая ссылки на все текстовые представления (которые ссылаются на суперпредставления вплоть до root-)
Показать ещё 4 комментария
21

Чтобы завершить ответ Август, возможная реализация предлагаемой функции (см. делегат UITextField).

Я не тестировал код domness, но мой не застревает, если пользователь достиг предела, и он совместим с новой строкой, которая приходит на замену меньшим или равным.

-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    //limit the size :
    int limit = 20;
    return !([textField.text length]>limit && [string length] > range.length);
}
  • 0
    Это должен быть принятый ответ.
17

Вы не можете сделать это напрямую - UITextField не имеет атрибута maxLength, но вы можете установить делегат UITextField's, а затем использовать:

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
  • 5
    Я согласен, это лучший способ продвинуться вперед, но это все равно что взломать. Отправьте в Apple отчет об ошибке, в котором вы хотели бы видеть свойство для длины текста. Я определенно заинтересован в этом также.
  • 5
    @avocade, это не хак: это пример, где вы должны сделать базовый код фреймворка, который Apple должен был сделать для вас. Есть много примеров этого в iOS SDK.
13

Часто у вас есть несколько полей ввода различной длины.

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    int allowedLength;
    switch(textField.tag) {
        case 1: 
            allowedLength = MAXLENGTHNAME;      // triggered for input fields with tag = 1
            break;
        case 2:
            allowedLength = MAXLENGTHADDRESS;   // triggered for input fields with tag = 2
            break;
        default:
            allowedLength = MAXLENGTHDEFAULT;   // length default when no tag (=0) value =255
            break;
    }

    if (textField.text.length >= allowedLength && range.length == 0) {
        return NO; // Change not allowed
    } else {
        return YES; // Change allowed
    }
}
12

Лучший способ - настроить уведомление об изменении текста. В -awakeFromNib вашего метода контроллера вида вы хотите:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(limitTextField:) name:@"UITextFieldTextDidChangeNotification" object:myTextField];

Затем в том же классе добавьте:

- (void)limitTextField:(NSNotification *)note {
    int limit = 20;
    if ([[myTextField stringValue] length] > limit) {
        [myTextField setStringValue:[[myTextField stringValue] substringToIndex:limit]];
    }
}

Затем подключите выход myTextField к вашему UITextField, и он не позволит вам добавлять больше символов после достижения предела. Не забудьте добавить это к вашему методу dealloc:

[[NSNotificationCenter defaultCenter] removeObserver:self name:@"UITextFieldTextDidChangeNotification" object:myTextField];
  • 0
    вам нужно бросить ноти. когда ты уйдешь
  • 0
    Хотя я сделал это, чтобы удалить ошибки> myTextField.text = [myTextField.text substringToIndex: limit];
11

Я создал this Подкласс UITextFieldLimit:

  • Поддерживается несколько текстовых полей.
  • Задайте ограничение длины текста
  • Предотвращение пасты
  • Отображает метку левых символов внутри текстового поля, скрывается, когда вы прекращаете редактирование.
  • Встряхните анимацию, когда никаких символов не осталось.

Возьмите UITextFieldLimit.h и UITextFieldLimit.m из этого репозитория GitHub:

https://github.com/JonathanGurebo/UITextFieldLimit

и начните тестирование!

Отметьте созданный раскадрой UITextField и привяжите его к моему подклассу с помощью Identity Inspector:

Изображение 5339

Затем вы можете связать его с IBOutlet и установить ограничение (по умолчанию 10).


Ваш файл ViewController.h должен содержать: (если вы не хотите изменять настройку, например, ограничение)

#import "UITextFieldLimit.h"

/.../

@property (weak, nonatomic) IBOutlet UITextFieldLimit *textFieldLimit; // <--Your IBOutlet

Ваш файл ViewController.m должен @synthesize textFieldLimit.


Задайте ограничение длины текста в файле ViewController.m:

- (void)viewDidLoad
{
    [super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.

    [textFieldLimit setLimit:25];// <-- and you won't be able to put more than 25 characters in the TextField.
}

Надеюсь, что класс поможет вам. Удачи!

  • 0
    Для небольшой потребности в ограничении персонажа, я думаю, добавление вашего класса было бы просто излишним.
  • 0
    Зависит от того, для чего тебе нужен предел ... Но да, ты прав.
Показать ещё 1 комментарий
11

Этого должно быть достаточно, чтобы решить проблему (замените 4 пределом u want). Просто не забудьте добавить делегата в IB.

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
     NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
     return (newString.length<=4);
}
7

версия Swift 3 // ***** Это НЕ работает с Swift 2.x! *****//

Сначала создайте новый файл Swift: TextFieldMaxLength.swift, и затем добавьте следующий код:

import UIKit

private var maxLengths = [UITextField: Int]()

extension UITextField {

   @IBInspectable var maxLength: Int {

      get {

          guard let length = maxLengths[self] 
             else {
                return Int.max
      }
      return length
   }
   set {
      maxLengths[self] = newValue
      addTarget(
         self,
         action: #selector(limitLength),
         for: UIControlEvents.editingChanged
      )
   }
}
func limitLength(textField: UITextField) {
    guard let prospectiveText = textField.text,
        prospectiveText.characters.count > maxLength
    else {
        return
    }

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

а затем вы увидите в Storyboard новое поле (Max Length), когда вы выберете любой TextField

если у вас есть еще вопросы, посмотрите эту ссылку: http://www.globalnerdy.com/2016/05/18/ios-programming-trick-how-to-use-xcode-to-set-a-text-fields-maximum-length-visual-studio-style/

  • 0
    Предупреждение, эта глобальная переменная создает утечки памяти, удерживая ссылки на все текстовые представления.
7

Я смоделирую фактическую замену строки, которая должна произойти, чтобы вычислить длину будущей строки:

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {

    NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];

    if([newString length] > maxLength)
       return NO;

    return YES;
}
6

Следующий код похож на ответ "больной", но правильно обрабатывает операции копирования и вставки. Если вы попытаетесь вставить текст, который превышает лимит, следующий код усекает текст, чтобы он соответствовал пределу, а не полностью отказывался от операции вставки.

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    static const NSUInteger limit = 70; // we limit to 70 characters
    NSUInteger allowedLength = limit - [textField.text length] + range.length;
    if (string.length > allowedLength) {
        if (string.length > 1) {
            // get at least the part of the new string that fits
            NSString *limitedString = [string substringToIndex:allowedLength];
            NSMutableString *newString = [textField.text mutableCopy];
            [newString replaceCharactersInRange:range withString:limitedString];
            textField.text = newString;
        }
        return NO;
    } else {
        return YES;
    }
}
6

Используя построитель интерфейсов, вы можете связать и получить событие "Редактирование изменено" в любой из ваших функций. Теперь вы можете установить проверку длины

- (IBAction)onValueChange:(id)sender 
{
    NSString *text = nil;
    int MAX_LENGTH = 20;
    switch ([sender tag] ) 
    {
        case 1: 
        {
            text = myEditField.text;
            if (MAX_LENGTH < [text length]) {
                myEditField.text = [text substringToIndex:MAX_LENGTH];
            }
        }
            break;
        default:
            break;
    }

}
5

Существует общее решение для установки максимальной длины в Swift. С IBInspectable вы можете добавить новый атрибут в инспекторе атрибутов XCode. Изображение 5340

import UIKit
private var maxLengths = [UITextField: Int]()
extension UITextField {

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

    func limitLength(textField: UITextField) {
        guard let prospectiveText = textField.text
            where prospectiveText.characters.count > maxLength else {
                return
        }
        let selection = selectedTextRange
        text = prospectiveText.substringWithRange(
            Range<String.Index>(prospectiveText.startIndex ..< prospectiveText.startIndex.advancedBy(maxLength))
        )
        selectedTextRange = selection
    }

}
  • 1
    Один здесь. Этот должен получить больше голосов.
  • 0
    Чистое и идеальное решение
Показать ещё 1 комментарий
5

Чтобы заставить его работать с вырезанием и вставкой строк любой длины, я бы предложил изменить функцию на что-то вроде:

#define MAX_LENGTH 20

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
    {
        NSInteger insertDelta = string.length - range.length;

        if (textField.text.length + insertDelta > MAX_LENGTH)
        {
           return NO; // the new string would be longer than MAX_LENGTH
        }
        else {
            return YES;
        }
    }
3

swift 3.0

Этот код работает отлично, когда вы вставляете строку больше, чем ваши ограничения символов.

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
        let str = (textView.text + text)
        if str.characters.count <= 10 {
            return true
        }
        textView.text = str.substring(to: str.index(str.startIndex, offsetBy: 10))
        return false
    }

Спасибо за ваши голоса.:)

  • 2
    UITextField, а не UITextView.
3

Swift 2.0 +

Прежде всего создайте класс для этого процесса. Позволяет называть его StringValidator.swift.

Затем просто вставьте в него следующий код.

import Foundation

extension String {

func containsCharactersIn(matchCharacters: String) -> Bool {
let characterSet = NSCharacterSet(charactersInString: matchCharacters)
return self.rangeOfCharacterFromSet(characterSet) != nil
}

func containsOnlyCharactersIn(matchCharacters: String) -> Bool {
let disallowedCharacterSet = NSCharacterSet(charactersInString: matchCharacters).invertedSet
return self.rangeOfCharacterFromSet(disallowedCharacterSet) == nil
}


func doesNotContainCharactersIn(matchCharacters: String) -> Bool {
let characterSet = NSCharacterSet(charactersInString: matchCharacters)
return self.rangeOfCharacterFromSet(characterSet) == nil
}

func isNumeric() -> Bool
{
let scanner = NSScanner(string: self)
scanner.locale = NSLocale.currentLocale()

return scanner.scanDecimal(nil) && scanner.atEnd
}

}

Теперь сохраните класс.....

Usage..

Теперь перейдите к классу viewController.swift и создайте свои текстовые поля как..

@IBOutlet weak var contactEntryTxtFld: UITextField! //First textfield
@IBOutlet weak var contactEntryTxtFld2: UITextField!   //Second textfield

Теперь перейдите к методу textChangeCharactersInRange и используйте следующее.

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    if string.characters.count == 0 {
        return true
    }
    let latestText = textField.text ?? ""
    let checkAbleText = (latestText as NSString).stringByReplacingCharactersInRange(range, withString: string)


    switch textField {

    case contactEntryTxtFld:
        return checkAbleText.containsOnlyCharactersIn("0123456789") && prospectiveText.characters.count <= 5

    case contactEntryTxtFld2:
        return checkAbleText.containsOnlyCharactersIn("0123456789") && prospectiveText.characters.count <= 5

    default:
        return true
    }

}

Не забудьте установить делегатский протокол/методы текстовых полей.

Позвольте мне объяснить об этом... Я использую простой процесс расширения строки, который я написал внутри другого класса. Теперь я просто вызываю эти методы расширения из другого класса, где мне это нужно, добавляя проверку и максимальное значение.

Особенности...

  • Он установит максимальный предел определенного текстового поля.
  • Он установит тип принятых ключей для определенного текстового поля.

Типы...

containsOnlyCharactersIn//принимает только символы.

containsCharactersIn//принимает комбинацию символов

doesNotContainsCharactersIn//Не принимает символы

Надеюсь, это помогло.... Спасибо..

2

Используйте расширение ниже, чтобы установить максимальную длину символов UITextField и UITextView.

Swift 4.0

    private var kAssociationKeyMaxLength: Int = 0
    private var kAssociationKeyMaxLengthTextView: 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)
                addTarget(self, action: #selector(checkMaxLength), for: .editingChanged)
            }
        }

        @objc func checkMaxLength(textField: UITextField) {
            guard let prospectiveText = self.text,
                prospectiveText.count > maxLength
                else {
                    return
            }

            let selection = selectedTextRange

            let indexEndOfText = prospectiveText.index(prospectiveText.startIndex, offsetBy: maxLength)
            let substring = prospectiveText[..<indexEndOfText]
            text = String(substring)

            selectedTextRange = selection
        }
    }

    extension UITextView:UITextViewDelegate {


    @IBInspectable var maxLength: Int {
        get {
            if let length = objc_getAssociatedObject(self, &kAssociationKeyMaxLengthTextView) as? Int {
                return length
            } else {
                return Int.max
            }
        }
        set {
            self.delegate = self

            objc_setAssociatedObject(self, &kAssociationKeyMaxLengthTextView, newValue, .OBJC_ASSOCIATION_RETAIN)
        }
    }

    public func textViewDidChange(_ textView: UITextView) {
        checkMaxLength(textField: self)
    }
    @objc func checkMaxLength(textField: UITextView) {
        guard let prospectiveText = self.text,
            prospectiveText.count > maxLength
            else {
                return
        }

        let selection = selectedTextRange

        let indexEndOfText = prospectiveText.index(prospectiveText.startIndex, offsetBy: maxLength)
        let substring = prospectiveText[..<indexEndOfText]
        text = String(substring)

        selectedTextRange = selection
    }
}

Вы можете установить предел ниже.

Изображение 5341

  • 0
    лучший ответ на сегодняшний день ,, спасибо большое отличное решение, когда есть много текстовых полей, которые нуждаются в различной длине
  • 0
    Действительно отличное решение для ограничения ввода символов текстового поля и текста. Его сохранить строки кода и время тоже для разработчика ... :)
2

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
}
  • 0
    Почему guard ?
  • 0
    проверьте, если текст ноль, если вы хотите, вы также можете использовать, если @oddRaven
2

Я даю дополнительный ответ на основе @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)
        }
    }

    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
    }

    //The method is used to cancel the check when use 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
    }

}
2

Для Xamarin:

YourTextField.ShouldChangeCharacters = 
delegate(UITextField textField, NSRange range, string replacementString)
        {
            return (range.Location + replacementString.Length) <= 4; // MaxLength == 4
        };
2

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

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
int MAX_LENGHT = 5;
    if([string isEqualToString:@"\n"])
    {
        [textField resignFirstResponder];
        return FALSE;
    }
    else if(textField.text.length > MAX_LENGHT-1)
    {
        if([string isEqualToString:@""] && range.length == 1)
        {
            return TRUE;
        }
        else
        {
            return FALSE;
        }
    }
    else
    {
        return TRUE;
    }
}
1

Если ваша цель ограничить количество слов, чтобы убедиться, что текст будет вписываться в UILabel в другом месте, я бы избегал использовать число символов. Он ломается с некоторыми эможи (попытка усечения двойного размера emoji, скорее всего, приведет к краху вашего приложения). Это также проблема с некоторыми языками, такими как японский и китайский, которые имеют двухэтапный входной процесс, когда простой счет просто не будет работать.

Я построил подкаталог подкаталогов UITextField (MPC_CharacterLimitedTextField в github). Вы кормите его ожидаемой шириной ярлыка вывода, и он будет обрабатывать все языки, emoji и вопросы вставки. Он будет собирать только столько полных символов, которые будут вписываться в метку, независимо от количества символов. Там есть демо в проекте, чтобы вы могли проверить его, чтобы узнать, что вам нужно. Надеюсь, это поможет любому, у кого были те же проблемы с выходной длиной, что и я.

1

Я сделал это в Swift для ограничения на 8 символов при использовании цифровой клавиатуры.

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    return !(textField.text?.characters.count == MAX_LENGTH && string != "")
}

Мне пришлось проверять строку!= "", чтобы кнопка удаления могла работать на цифровой клавиатуре, иначе она не позволила бы удалять символы в текстовом поле после достижения максимального значения.

1

Используйте этот код здесь RESTRICTED_LENGTH - длина, которую вы хотите ограничить для текстового поля.

   - (BOOL)textField:(UITextField *)textField     shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    if (textField == nameTF) {
    int limit = RESTRICTED_LENGTH - 1;
    return !([textField.text length]>limit && [string length] > range.length);
    }
   else
   {
    return YES;
   }

return NO;

}
1

У меня есть открытый подкласс UITextField, STATextField, который предлагает эту функциональность (и многое другое) с ее свойством maxCharacterLength.

1

Я добавил расширение UITextField, чтобы добавить к нему свойство maxLength.

Он основан на Xcode 6 IBInspectables, поэтому вы можете установить предел maxLength для построителя интерфейса.

Вот реализация:

UITextField + MaxLength.h

#import <UIKit/UIKit.h>

@interface UITextField_MaxLength : UITextField<UITextFieldDelegate>

@property (nonatomic)IBInspectable int textMaxLength;
@end

UITextField + MaxLength.m

#import "UITextField+MaxLength.h"

@interface UITextField_MaxLength()

@property (nonatomic, assign) id <UITextFieldDelegate> superDelegate;

@end

@implementation UITextField_MaxLength

- (BOOL)textField:(UITextField *) textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {

    //validate the length, only if it set to a non zero value
    if (self.textMaxLength>0) {
        if(range.length + range.location > textField.text.length)
            return NO;

        if (textField.text.length+string.length - range.length>self.textMaxLength) {
            return NO;
        }
    }

    //if length validation was passed, query the super class to see if the delegate method is implemented there
    if (self.superDelegate && [self.superDelegate respondsToSelector:@selector(textField:shouldChangeCharactersInRange:replacementString:)]) {
        return [self.superDelegate textField:textField shouldChangeCharactersInRange:range replacementString:string];
    }
    else{
        //if the super class does not implement the delegate method, simply return YES as the length validation was passed
        return YES;
    }
}

- (void)setDelegate:(id<UITextFieldDelegate>)delegate {
    if (delegate == self)
        return;
    self.superDelegate = delegate;
    [super setDelegate:self];
}

//forward all non overriden delegate methods
- (id)forwardingTargetForSelector:(SEL)aSelector {
    if ([self.superDelegate  respondsToSelector:aSelector])
        return self.superDelegate;

    return [super forwardingTargetForSelector:aSelector];
}

- (BOOL)respondsToSelector:(SEL)aSelector {
    if ([self.superDelegate respondsToSelector:aSelector])
        return YES;

    return [super respondsToSelector:aSelector];
}
@end
1

Доведено до 1 строки кода:)

Установите делегат текстового представления на "self", затем добавьте <UITextViewDelegate> в ваш .h и следующий код в вашем .m.... вы можете настроить число "7", чтобы быть тем, что вы хотите, чтобы ваше МАКСИМАЛЬНОЕ число символов.

-(BOOL)textView:(UITextView *)a shouldChangeTextInRange:(NSRange)b replacementText:(NSString *)c {
    return ((a.text.length+c.length<=7)+(c.length<1)+(b.length>=c.length)>0);
}

Этот код учитывает ввод новых символов, удаление символов, выбор символов, затем ввод или удаление, выбор символов, вырезание, вставка в общем и выбор символов и вставка.

Готово!

:


Альтернативно, еще один классный способ записать этот код с битовыми операциями будет

-(BOOL)textView:(UITextView *)a shouldChangeTextInRange:(NSRange)b replacementText:(NSString *)c {
    return 0^((a.text.length+c.length<=7)+(c.length<1)+(b.length>=c.length));
}
1

теперь сколько символов u хотите просто дать значения

 - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range   replacementString:(NSString *)string {
     NSUInteger newLength = [textField.text length] + [string length] - range.length;
     return (newLength > 25) ? NO : YES;
  }
1

Другие ответы не обрабатывают случай, когда пользователь может вставить длинную строку из буфера обмена. Если я вставлю длинную строку, ее нужно просто усечь, но показать. Используйте это в своем делегате:

static const NSUInteger maxNoOfCharacters = 5;

-(IBAction)textdidChange:(UITextField * )textField
{
NSString * text = textField.text;

if(text.length > maxNoOfCharacters)
{
    text = [text substringWithRange:NSMakeRange(0, maxNoOfCharacters)];
    textField.text = text;
}

// use 'text'

}
0

Как насчет этого простого подхода. Это работает нормально для меня.

extension UITextField {

    func  charactersLimit(to:Int) {

        if (self.text!.count > to) {
            self.deleteBackward()
        }
    }
}

Затем:

someTextField.charactersLimit(to:16)
0

Вы также можете сделать это с помощью NotificationCenter в Swift 4

NotificationCenter.default.addObserver(self, selector: #selector(self.handleTextChange(recognizer:)), name: NSNotification.Name.UITextFieldTextDidChange, object: yourTextField)

    @objc func handleTextChange(recognizer: NSNotification) {
            //max length is 50 charater max
            let textField = recognizer.object as! UITextField

            if((textField.text?.count)! > 50) {
                let newString: String? = (textField.text as NSString?)?.substring(to: 50)
                textField.text = newString

            }         
        }
0

для Swift 3.1 или более поздней версии

сначала добавьте протокол UITextFieldDelegate

как: -

class PinCodeViewController: UIViewController, UITextFieldDelegate { 
.....
.....
.....

}

после этого создайте свой UITextField и установите делегат

Complete Exp: -

import UIKit

class PinCodeViewController: UIViewController, UITextFieldDelegate {

let pinCodetextField: UITextField = {
    let tf = UITextField()
    tf.placeholder = "please enter your pincode"
    tf.font = UIFont.systemFont(ofSize: 15)
    tf.borderStyle = UITextBorderStyle.roundedRect
    tf.autocorrectionType = UITextAutocorrectionType.no
    tf.keyboardType = UIKeyboardType.numberPad
    tf.clearButtonMode = UITextFieldViewMode.whileEditing;
    tf.contentVerticalAlignment = UIControlContentVerticalAlignment.center
 return tf
  }()


 override func viewDidLoad() {
   super.viewDidLoad()
   view.addSubview(pinCodetextField)
    //----- setup your textfield anchor or position where you want to show it----- 


    // after that 
pinCodetextField.delegate = self // setting the delegate

 }
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    return !(textField.text?.characters.count == 6 && string != "")
     } // this is return the maximum characters in textfield 
    }
0

Я хочу добавить к ответу @sickp.

В коде Swift есть проблема, которая возникает с любым многобайтовым текстом (например, emojis). NSRange и String в Swift несовместимы, поэтому разочарование в том, что класс делегата их объединяет. Хитрость - просто преобразовать объекты String в NSString. Правильное решение, основанное на том, что написал @sickp, на самом деле таково:

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

    let currentText = (textField.text as NSString?) ?? NSString()
    let currentCharacterCount = currentText.length
    if range.length + range.location > currentCharacterCount {
        return false
    }
    let newLength = currentText.replacingCharacters(in: range, with: string).characters.count
    return newLength <= 25
}
0

Для Swift 2.1 +

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

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

    let newLength = textField.text!.characters.count + string.characters.count - range.length
    return newLength <= 25
}

Надеюсь, что это поможет

0

Чуть больше, чем отвечать на исходный вопрос и расширяя ответ Frouo, вот расширения для обрезки строки с пробелом и максимальной длиной и использования этих расширений String для обрезки UITextField до максимальной длины:

// In String_Extensions.swift

extension String {

  func trimmedString() -> String {
    var trimmedString = self.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
    let components = trimmedString.componentsSeparatedByCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()).filter { count($0) > 0 }
    return " ".join(components)
  }

  func trimmedStringToMaxLength(maxLength: Int) -> String {
    return trimmedString().substringToIndex(advance(startIndex, min(count(self), maxLength))).trimmedString()
  }

}

// In UITextField_Extensions.swift

private var maxLengthDictionary = [UITextField : Int]()
private var textFieldMaxLength = 20

extension UITextField {

  @IBInspectable var maxLength: Int {
    get {
      if let maxLength = maxLengthDictionary[self] {
        return maxLength
      } else {
        return textFieldMaxLength
      }
    }
    set {
      maxLengthDictionary[self] = newValue < textFieldMaxLength + 1 ? newValue : textFieldMaxLength
    }
  }

  func trimAndLimitToMaxLength() {
    text = text.trimmedStringToMaxLength(maxLength)
  }

}

let someTextField = UITextField()
let someString = "   This   is   a   string   that   is longer than allowable for a text field.   "
someTextField.text = someString
someTextField.trimAndLimitToMaxLength()
println(someTextField.text) // Prints "This is a string tha"
let anotherTextField = UITextField()
anotherTextField.maxLength = 5
anotherTextField.text = someString
anotherTextField.trimAndLimitToMaxLength()
println(anotherTextField.text) // Prints "This"

trimAndLimitToMaxLength() может использоваться в UITextFieldDelegate textFieldDidEndEditing(_:), чтобы пользователь мог ввести или вставить более длинную, чем приемлемую строку, а затем сократить ее или просто отключить вход на максимальной длине. При этом я также установил атрибутные стили текста, чтобы указать любую часть текста, которая выходит за допустимую длину (например, [NSBackgroundColorAttributeName : UIColor.redColor(), NSForegroundColorAttributeName : UIColor.whiteColor(), NSStrikethroughStyleAttributeName : NSNumber(int: 1)]

  • 0
    Разве глобальный словарь не создает утечек памяти, удерживая ссылки на все текстовые представления (которые ссылаются на суперпредставления вплоть до root-)
0

Это ограничивает количество символов, но также убедитесь, что вы можете вставлять их в поле до максимального предела.

- (void)textViewDidChange:(UITextView *)textView
{
    NSString* str = [textView text];
    str = [str substringToIndex:MIN(1000,[str length])];
    [textView setText:str];

    if([str length]==1000) {
        // show some label that you've reached the limit of 1000 characters
    }
}
0

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

-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range  replacementString:(NSString *)string
{
     int setrange = 20;
     return !([textField.text length]>setrange && [string length] > range.length);
}
0
(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];

    if ([txt_name.text length]>100)
    {
        return NO;
    }

    return YES;
}
0

Проблема с некоторыми из приведенных выше ответов: Например, у меня есть текстовое поле, и я должен установить ограничение на 15 символов, а затем останавливается после ввода 15-го символа. но они не позволяют удалять. То есть кнопка удаления также не работает. Поскольку я столкнулся с той же проблемой. Вышел с решением, приведенным ниже. Работает идеально для меня

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
 if(textField.tag==6)
 {
    if ([textField.text length]<=30)
    {
        return YES;   
    }
    else if([@"" isEqualToString:string])
    {
        textField.text=[textField.text substringToIndex:30 ];
    }

    return NO;
 }
 else
 {
    return YES;
 }
}

У меня есть текстовое поле, чей тег я установил "6" и я ограничил max char limit = 30; отлично работает в каждом случае

-2
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    if (textField.text.length >= 50) {
        return NO;
    }
    return YES;
}
  • 0
    Это не заставит вас вводить символы больше или равные 50.
-5

Я нашел это быстро и просто

- (IBAction)backgroundClick:(id)sender {
    if (mytext.length <= 7) {
        [mytext resignFirstResponder];
    } else {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Too Big" 
                                                        message:@"Please Shorten Name"
                                                       delegate:nil 
                                              cancelButtonTitle:@"Cancel"
                                              otherButtonTitles:nil];
        [alert show];
        [alert release];
    }
}
  • 0
    Такое использование UIAlertView s не рекомендуется Apple. Вы должны зарезервировать оповещения для важных сообщений и просто запретить ввод, как в принятом ответе.
  • 0
    Не правильный путь! --- Пользователь узнает о размере ввода после вставки полной строки!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню