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

问题描述 投票:53回答:16

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

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

我只是不知道如何实际实现它或我应该换出哪个“textfield”我的自定义命名为UITextField

ios string swift uitextfield character
16个回答
95
投票
  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
}

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


2
投票

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

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

2
投票

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

    class SignUPViewController: UIViewController , UITextFieldDelegate {

       @IBOutlet weak var userMobileNoTextFiled: UITextField!

        override func viewDidLoad() {
            super.viewDidLoad()

1
投票

在Swift4工作

//步骤1设置UITextFieldDelegate

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

//步骤2设置委托 userMobileNoTextFiled.delegate = self // set delegate}

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

// STEP 3调用func

Fattie answer

1
投票

更新此extension UITextField { /// Runtime key private struct AssociatedKeys { /// max lenght key static var maxlength: UInt8 = 0 /// temp string key static var tempString: UInt8 = 0 } /// Limit the maximum input length of the textfiled @IBInspectable var maxLength: Int { get { return objc_getAssociatedObject(self, &AssociatedKeys.maxlength) as? Int ?? 0 } set { objc_setAssociatedObject(self, &AssociatedKeys.maxlength, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC) addTarget(self, action: #selector(handleEditingChanged(textField:)), for: .editingChanged) } } /// temp string private var tempString: String? { get { return objc_getAssociatedObject(self, &AssociatedKeys.tempString) as? String } set { objc_setAssociatedObject(self, &AssociatedKeys.tempString, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC) } } /// When the text changes, process the amount of text in the input box so that its length is within the controllable range. @objc private func handleEditingChanged(textField: UITextField) { /// Special Processing for Chinese Input Method guard markedTextRange == nil else { return } if textField.text?.count == maxLength { /// SET lastQualifiedString where text length == max lenght tempString = textField.text } else if textField.text?.count ?? 0 < maxLength { /// clear lastQualifiedString when text lengeht > maxlength tempString = nil } /// keep current text range in arcgives let archivesEditRange: UITextRange? if textField.text?.count ?? 0 > maxLength { /// if text length > maxlength,remove last range,to move to -1 postion. let position = textField.position(from: safeTextPosition(selectedTextRange?.start), offset: -1) ?? textField.endOfDocument archivesEditRange = textField.textRange(from: safeTextPosition(position), to: safeTextPosition(position)) } else { /// just set current select text range archivesEditRange = selectedTextRange } /// main handle string max length textField.text = tempString ?? String((textField.text ?? "").prefix(maxLength)) /// last config edit text range textField.selectedTextRange = archivesEditRange } /// get safe textPosition private func safeTextPosition(_ optionlTextPosition: UITextPosition?) -> UITextPosition { /* beginningOfDocument -> The end of the the text document. */ return optionlTextPosition ?? endOfDocument } }

谢谢

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    let text = textField.text ?? ""

    return text.count - range.length + string.count <= 10
}

0
投票

这是一个避免不必要的字符串操作的Swift 3.2+替代方案。在这种情况下,最大长度为10:

    override func viewDidLoad() {
        super.viewDidLoad()

        textfield.delegate = self

    }

0
投票

我使用此步骤,首先在viewdidload中设置委托文本字段。

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

然后在包含UITextFieldDelegate之后应该更改字符。

    class YorsClassName : UITextFieldDelegate {

    }

0
投票

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

  1. 添加委托以查看控制器和asign委托
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    if textField.text?.count == 1 {
        return false
    }
    return true
}
  1. 检查textfield允许的字符数
http://www.swiftdevcenter.com/max-character-limit-of-uitextfield-and-allowed-characters-swift/

注意:这里我只检查了textField中允许的char


0
投票

斯威夫特5 图片来源: self.textField.maxLength = 10 只需编写一个来设置最大字符长度

click here

更多细节qazxsw poi


101
投票

Dec 2017. Swift 4.

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

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

This finally fixes one of the stupidest problems in 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?.prefix(maxLength)
    }
}

就这么简单。


脚注 - 这些天安全截断一个String迅速,你只需.prefix(n)


An even simpler one-off version...

以上修复了项目中的所有文本字段。

如果您只想将一个特定的文本字段简单地限制为“4”,那就是......

class PinCodeEntry: UITextField {

    override func didMoveToSuperview() {

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

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

唷!这里的所有都是它的。

(只是BTW,这里有一个与UITextView相关的非常有用的提示,https://stackoverflow.com/a/42333832/294884


17
投票

Swift 4,只需使用:

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

9
投票

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
}

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
  }

}

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的更新解决方案,带有弱映射以防止内存泄漏和其他修复

shouldChangeCharactersIn

3
投票

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

UITextFieldDelegate

2
投票

我有什么可以补充阿拉丁的回答:

  1. 您的视图控制器应符合class MyViewController: UIViewController, UITextViewDelegate { } textField(_:shouldChangeCharactersInRange:replacementString:)
  2. 设置文本字段的委托:要设置委托,您可以控制从文本字段拖动到故事板中的视图控制器。我认为这比在代码中设置更好
  3. 在视图控制器中实现该方法: 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
投票

我基于@Frouo给出了补充答案。我认为他的回答是最美好的方式。因为它是我们可以重复使用的通用控件。这里没有泄漏问题。

func textField(_ textField: UITextField, 
               shouldChangeCharactersIn range: NSRange, 
               replacementString string: String) -> Bool {
    return textField.text!.count < 10 || string == ""
}
© www.soinside.com 2019 - 2024. All rights reserved.