在Swift中设置UITextField的最大字符长度

时间:2015-07-12 00:32:58

标签: ios string swift uitextfield character

我知道还有其他主题,但我似乎无法找到如何实现它。

我试图将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 
}

我只是不知道如何实际实现它或者#34; textfield&#34;我应该换掉我的自定义名为UITextField

21 个答案:

答案 0 :(得分:93)

2017年12月.Swift 4。

请注意您将在网上看到的有关此问题的大部分示例代码都已过时

只需将以下内容粘贴到项目中的任何Swift文件中即可。将文件命名为any,例如“Handy.swift”

这最终解决了iOS中最愚蠢的问题之一:

enter image description here

您的文字字段现在有.maxLength

在开发过程中在storyboard中设置该值是完全可以的,或者在应用程序运行时将其设置为代码。

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

就这么简单。

(注意:“safelyLimitedTo #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) }
}

唷! 这就是它的全部内容。

(顺便说一下,这是一个与UIText相关的非常有用的提示查看https://stackoverflow.com/a/42333832/294884

答案 1 :(得分:84)

  1. 您的视图控制器应符合UITextFieldDelegate,如下所示:

    class MyViewController: UIViewController, UITextFieldDelegate {
    
    }
    
  2. 设置文本字段的代理:myTextField.delegate = self

  3. 在视图控制器中实施该方法:textField(_:shouldChangeCharactersInRange:replacementString:)
  4. 所有在一起:

    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
    }
    

    How to program an iOS text field that takes only numeric input with a maximum length

答案 2 :(得分:17)

快捷键4,只需使用:

public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    return range.location < 10
}

答案 3 :(得分:8)

Steven Schmatz以同样的方式使用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
}

答案 4 :(得分:6)

我认为扩展对此更为方便。查看完整的答案here

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
  }

}

答案 5 :(得分:4)

由于文本字段地图,上面发布的其他解决方案会产生保留周期。此外,如果没有设置maxLength属性而不是人工Int.max构造,则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 } } 属性应该是可空的;如果更改了maxLength,目标将被设置多次。

这里有一个更新的Swift4解决方案,带有弱映射以防止内存泄漏和其他修复

public function particulars()
{
    return $this->hasOne('App\Sale','page_id');
}

and use 

$value->particulars->regular_price;

答案 6 :(得分:3)

我的shouldChangeCharactersIn的Swift 4版本

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
    }

答案 7 :(得分:2)

我有一些东西可以添加到Aladin的答案中:

  1. 您的视图控制器应符合UITextFieldDelegate

    class MyViewController: UIViewController, UITextViewDelegate {
    
    }
    
  2. 设置文本字段的委托: 要设置委托,您可以控制从文本字段拖动到故事板中的视图控制器。我认为这比在代码中设置

  3. 更可取
  4. 在视图控制器中实施该方法:textField(_:shouldChangeCharactersInRange:replacementString:)

答案 8 :(得分:2)

不使用委托的简单解决方案:

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

答案 9 :(得分: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)
            }
        }

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



    }

答案 10 :(得分:2)

这个答案适用于Swift 4,并且非常直接,能够让退格通过。

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

答案 11 :(得分:1)

在Swift4中工作

//第1步设置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
    //    }

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

答案 12 :(得分:1)

为此Fattie answer

更新
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) )
    }
}

答案 13 :(得分:1)

在Swift 4中阻止文本后,TextField限制字符

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


    if textField == self.txtDescription {
        let maxLength = 200
        let currentString: NSString = textField.text! as NSString
        let newString: NSString = currentString.replacingCharacters(in: range, with: string) as NSString
        return newString.length <= maxLength
    }

    return true


}

答案 14 :(得分:1)

以防万一,在将其应用于字符串之前,请不要忘记保护范围大小。 否则,如果用户执行此操作,则会崩溃:

输入最大长度的文本 插入内容(由于长度限制,不会插入任何内容,但iOS对此一无所知) 撤消插入(您会崩溃,原因范围将大于实际的字符串大小)

此外,使用iOS 13用户可能会通过手势意外触发

我建议您将此添加到您的项目中

extension String {
    func replace(with text: String, in range: NSRange) -> String? {
        guard range.location + range.length <= self.count else { return nil }
        return (self as NSString).replacingCharacters(in: range, with: text)
    }
}

并像这样使用它:

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    guard let newText = textView.text.replace(with: text, in: range) else { return false }
    return newText.count < maxNumberOfCharacters
}

否则,您将不断崩溃于应用程序中

答案 15 :(得分:0)

这是一个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
}

答案 16 :(得分:0)

我使用此步骤,首先在viewdidload中设置委托texfield。

    override func viewDidLoad() {
        super.viewDidLoad()

        textfield.delegate = self

    }

,然后在包含UITextFieldDelegate之后,应该应该使用ChangeCharactersIn。

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

答案 17 :(得分:0)

只需检查字符串中的字符数

  1. 添加委托以查看控制器anssign委托

class YorsClassName:UITextFieldDelegate {

}

  1. 检查允许用于文本字段的字符数

func textField(_ textField:UITextField,shouldChangeCharacters在范围内:NSRange,replacementString字符串:String)-> Bool {     如果textField.text?.count == 1 {         返回假     }     返回真 }

注意:在这里,我只检查了textField中允许的字符

答案 18 :(得分:0)

雨燕5
信用:http://www.swiftdevcenter.com/max-character-limit-of-uitextfield-and-allowed-characters-swift/
只需写一个即可设置最大字符长度

self.textField.maxLength = 10

更多详情click here

答案 19 :(得分:0)

如果您有多个textField可以在一页上进行各种长度检查,那么我发现了一个简单而又简短的解决方案。

class MultipleTextField: UIViewController {

    let MAX_LENGTH_TEXTFIELD_A = 10
    let MAX_LENGTH_TEXTFIELD_B = 11

    lazy var textFieldA: UITextField = {
        let textField = UITextField()
        textField.tag = MAX_LENGTH_TEXTFIELD_A
        textField.delegate = self
        return textField
    }()
    lazy var textFieldB: UITextField = {
        let textField = UITextField()
        textField.tag = MAX_LENGTH_TEXTFIELD_B
        textField.delegate = self
        return textField
    }()
}

extension MultipleTextField: UITextFieldDelegate {
    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        return (range.location < textField.tag) && (string.count < textField.tag)
    }
}

答案 20 :(得分:0)

1.设置你的文本框的委托:

 textField.delegate = self

2.在你的视图控制器中实现该方法:

// MARK: Text field delegate

extension ViewController: UITextFieldDelegate {
    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        return range.location < maxLength (maxLength can be any maximum length you can define)
    }
}