Установите максимальную длину символа UITextField - PullRequest
459 голосов
/ 11 января 2009

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

Ответы [ 43 ]

1005 голосов
/ 21 ноября 2009

Хотя класс UITextField не имеет свойства максимальной длины, эту функцию относительно просто получить, установив 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;
}

Swift

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.location, а вставка нескольких символов означает, что string содержит более одного символа.

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

Замечание об ошибке "отменить"

Как уже упоминалось в комментариях, есть ошибка с 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
    }

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

56 голосов
/ 11 января 2009

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

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

#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;}
}
51 голосов
/ 22 апреля 2015

Свифт 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
    }
}

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

enter image description here

21 голосов
/ 16 апреля 2009

Для завершения ответа Август возможна реализация предложенной функции (см. Делегат 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);
}
17 голосов
/ 11 января 2009

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

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
13 голосов
/ 07 сентября 2012

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

- (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 голосов
/ 11 января 2009

Лучший способ - настроить уведомление об изменении текста. В вашем -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];
11 голосов
/ 13 апреля 2014

Я создал этот UITextFieldLimit подкласс:

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

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

https://github.com/JonathanGurebo/UITextFieldLimit

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

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

Identity Inspector

Затем вы можете связать его с 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.
}

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

11 голосов
/ 20 августа 2012

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

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
     NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
     return (newString.length<=4);
}
7 голосов
/ 29 сентября 2016

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

и затем вы увидите в раскадровке новое поле (максимальная длина) при выборе любого 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/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...