it-swarm.com.ru

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

Я знаю, что есть другие темы по этому вопросу, но я не могу понять, как это реализовать. 

Я пытаюсь ограничить UITextField только 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

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

Для Swift 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
}

Допускается ввод только указанного набора символов в заданное текстовое поле

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

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

  return result
}

Как запрограммировать текстовое поле iOS, которое принимает только числовой ввод с максимальной длиной

69
Aladin

Декабрь 2017. Swift 4.

Позаботьтесь о том, чтобы большая часть кода примера, который вы увидите в Интернете об этой проблеме, очень устарела.

Просто вставьте следующее в любой файл Swift в вашем проекте. Назовите файл как угодно, например, «Handy.Swift»

Это наконец исправляет одну из самых глупых проблем в iOS:

 enter image description here

Ваши текстовые поля теперь имеют .maxLength.

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

// simply have this in any Swift file, say, 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?.safelyLimitedTo(length: maxLength)
    }
}

extension String
    {
    func safelyLimitedTo(length n: Int)->String {
        if (self.count <= n) {
            return self
        }
        return String( Array(self).prefix(upTo: n) )
    }
}

Это так просто.


(Примечание: «safeLimitedTo # length» - это просто вызов, который обрезает длину строки. У всех программистов Swift есть для этого собственное расширение, или просто используйте мой, который вы видите там.)


Еще более простая одноразовая версия ...

Выше исправлены текстовые поля все в вашем проекте.

Если вы просто хотите, чтобы одно конкретное текстовое поле было просто ограничено словом "4", и это все ...

class PinCodeEntry: UITextField {

    override func didMoveToSuperview() {

        super.didMoveToSuperview()
        addTarget(self, action: #selector(fixMe), for: .editingChanged)
    }

    @objc private func fixMe() { text = text?.safelyLimitedTo(length 4) }
}

Уф! Это все, что нужно сделать.

(Кстати, вот еще один очень полезный совет, связанный с UITextView, https://stackoverflow.com/a/42333832/294884 )

84
Fattie

Swift 4, просто используйте:

public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    return range.location < 10
}
13
Сергей Билык

Стивен Шмац сделал то же самое, но с помощью 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
}
7
Pavlos

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

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
  }

}
6
ZaEeM ZaFaR

Другие решения, опубликованные выше, создают цикл сохранения из-за карты текстового поля. Кроме того, свойство maxLength должно иметь значение null, если оно не установлено, вместо искусственных конструкций Int.max; и цель будет установлена ​​несколько раз, если maxLength изменяется. 

Здесь обновленное решение для 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
    }
}
4
Angel G. Olloqui

My Swift 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
    }
2
aviran

Этот ответ предназначен для Swift 4 и довольно прост с возможностью пропустить пробел.

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

У меня есть кое-что, чтобы добавить к ответу Аладина:

  1. Ваш контроллер представления должен соответствовать UITextFieldDelegate

    class MyViewController: UIViewController, UITextViewDelegate {
    
    }
    
  2. Установите делегата вашего текстового поля: Чтобы установить делегата, вы можете управлять перетаскиванием из текстового поля на контроллер представления в раскадровке. Я думаю, что это предпочтительнее, чем устанавливать его в коде

  3. Реализуйте метод в вашем контроллере представления: textField(_:shouldChangeCharactersInRange:replacementString:)

2
SwiftMatt

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


        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
        }



    }
2
Victor Choy

обновление для этого Толстяк ответ

import UIKit

extension UITextField {

    /// Runtime 键
    private struct AssociatedKeys {

        static var maxlength: UInt8 = 0
        static var lastString: UInt8 = 0
    }

    /// 最大输入长度
    @IBInspectable var maxLength: Int {
        get {
            return objc_getAssociatedObject(self, &AssociatedKeys.maxlength) as? Int ?? 0
        }
        set(newValue) {
            objc_setAssociatedObject(self, &AssociatedKeys.maxlength, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            addTarget(self, action: #selector(fix), for: .editingChanged)
        }
    }

    /// 最后一个符合条件的规则
    private var lastQualifiedString: String? {
        get {
            return objc_getAssociatedObject(self, &AssociatedKeys.lastString) as? String
        }
        set(newValue) {
            objc_setAssociatedObject(self, &AssociatedKeys.lastString, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }

    @objc func fix(textField: UITextField) {

        guard markedTextRange == nil else { return }

        /// 如果 个数 为最大个数
        /// 在字典中,保存 最大数据
        if textField.text?.count == maxLength {

            /// 在 字典中保存 该数值
            lastQualifiedString = textField.text

            // 在 小于个数时 清除 数据
        } else if textField.text?.count ?? 0 < maxLength {
            lastQualifiedString = nil
        }

        let editRange: UITextRange?

        /// 如果 输入框内的个数大于 最大值
        if textField.text?.count ?? 0 > maxLength {

            /// 将选中的 range 向前移动一个位置
            let position = textField.position(from: safeTextPosition(selectedTextRange?.start), offset: -1) ?? textField.beginningOfDocument

            editRange = textField.textRange(from: safeTextPosition(position), to: safeTextPosition(position))
        } else {

            editRange = selectedTextRange
        }

        /// 配置 值
        textField.text = textField.text?.safelyLimitedTo(length: maxLength, safeText: lastQualifiedString)

        textField.selectedTextRange = editRange
    }

    /// 安全获取  UITextPosition
    private func safeTextPosition(_ optionlTextPosition: UITextPosition?) -> UITextPosition {

        /* beginningOfDocument -> The end and beginning of the the text document. */
        return optionlTextPosition ?? self.beginningOfDocument
    }
}

extension String {

    /// 比较后 决定 返回 text 还是 safetext
    ///
    /// - Parameters:
    ///   - n: 长度
    ///   - safeText: 安全字符串
    /// - Returns: 返回的值
    fileprivate func safelyLimitedTo(length n: Int, safeText: String?) -> String? {
        if (self.count <= n) {
            return self
        }
        return safeText ?? String( Array(self).prefix(upTo: n) )
    }
}
1
Z King

Работа в Swift4

// ШАГ 1 set UITextFieldDelegate

    class SignUPViewController: UIViewController , UITextFieldDelegate {

       @IBOutlet weak var userMobileNoTextFiled: UITextField!

        override func viewDidLoad() {
            super.viewDidLoad()

// ШАГ 2 установить делегата
userMobileNoTextFiled.delegate = self // установить делегата }

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

Простое решение без использования делегата:

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

Вот альтернатива 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
}
0
Greg Brown

Я использую этот шаг, сначала установите делегат texfield в viewdidload.

    override func viewDidLoad() {
        super.viewDidLoad()

        textfield.delegate = self

    }

а затем следует изменитьCharactersIn после включения UITextFieldDelegate.

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
                }
            }
    }
0
Jeri P.M

Просто сверьтесь с количеством символов в строке

  1. Добавить делегата для просмотра контроллера и делегата asign

class YorsClassName: UITextFieldDelegate {

}

  1. проверьте количество символов, разрешенных для текстового поля

func textField (_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replaceString string: String) -> Bool {if textField.text? .count == 1 {return false} вернуть true}

Примечание: здесь я проверил только разрешенный символ в textField

0
Akshaykumar Digrase