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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31363216/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 06:50:05  来源:igfitidea点击:

Set the maximum character length of a UITextField in Swift

iosstringswiftuitextfieldcharacter

提问by ishkur88

I know there are other topics on this but I can't seem to find out how to implement it.

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

I'm trying to limit a UITextField to only 5 Characters

我试图将 UITextField 限制为只有 5 个字符

Preferably Alphanumeric and - and . and _

最好是字母数字和 - 和。和 _

I've seen this code

我见过这个代码

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
}

and

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 
}

I just don't know how to actually implement it or which "textfield" should I swap out for my custom named UITextField

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

回答by Aladin

  1. Your view controller should conform to UITextFieldDelegate, like below:

    class MyViewController: UIViewController, UITextFieldDelegate {
    
    }
    
  2. Set the delegate of your textfield: myTextField.delegate = self

  3. Implement the method in your view controller : textField(_:shouldChangeCharactersInRange:replacementString:)
  1. 您的视图控制器应符合UITextFieldDelegate,如下所示:

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

  3. 在您的视图控制器中实现该方法: textField(_:shouldChangeCharactersInRange:replacementString:)

All together:

全部一起:

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
}

For Swift 4

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

Allowing only a specified set of characters to be entered into a given text field

只允许在给定的文本字段中输入一组指定的字符

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

如何编写仅接受最大长度数字输入的 iOS 文本字段

回答by Fattie

Dec 2017. Swift 4.

2017 年 12 月。斯威夫特 4。

Take care that much of the example code which you will see online regarding this problem is very out of date.

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

Paste the following into any Swift file in your project. You can name the file anything, for example, "Handy.swift"

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

This finally fixes one of the stupidest problems in iOS:

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

enter image description here

在此处输入图片说明

Your text fields now have a .maxLength.

您的文本字段现在有一个.maxLength.

It is completely OK to set that value in storyboard during development, or, set it in code while the app is running.

在开发期间在故事板中设置该值是完全可以的,或者在应用程序运行时在代码中设置它。

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

It's that simple.

就这么简单。



Footnote - these days to safely truncate a Stringin swift, you simply .prefix(n)

脚注 - 这些天来安全地String在 swift 中截断 a ,您只需.prefix(n)



An even simpler one-off version...

一个更简单的一次性版本......

The above fixes alltext fields in your project.

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

If you just want one particulartext field to simply be limited to say "4", and that's that...

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

class PinCodeEntry: UITextField {

    override func didMoveToSuperview() {

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

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

Phew! That's all there is to it.

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

(Just BTW, here's a similar very useful tip relating to UITextView, https://stackoverflow.com/a/42333832/294884)

(顺便说一句,这里有一个与 UIText View相关的非常有用的类似提示, https://stackoverflow.com/a/42333832/294884 )

回答by Сергей Билык

Swift 4, simply use:

Swift 4,只需使用:

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

回答by Pavlos

The same way Steven Schmatz did it but using Swift 3.0 :

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

回答by ZaEeM ZaFaR

I think extension is more handy for this. See full answer 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
  }

}

回答by Ashish Chauhan

Swift 5
Credit: http://www.swiftdevcenter.com/max-character-limit-of-uitextfield-and-allowed-characters-swift/
Just write one to set max char length

Swift 5
Credit: http://www.swiftdevcenter.com/max-character-limit-of-uitextfield-and-allowed-characters-swift/
只需写一个来设置最大字符长度

 self.textField.maxLength = 10

For more detial click here

更多详情请点击这里

回答by Angel G. Olloqui

Other solutions posted above produce a retain cycle due to the textfield map. Besides, the maxLengthproperty should be nullable if not set instead of artificial Int.maxconstructions; and the target will be set multiple times if maxLength is changed.

由于文本字段映射,上面发布的其他解决方案会产生一个保留周期。此外,maxLength如果不设置而不是人工Int.max构造,则该属性应该可以为空;如果 maxLength 改变,目标将被设置多次。

Here an updated solution for Swift4 with a weak map to prevent memory leaks and the other fixes

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

回答by ober

Simple solution without using delegate:

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

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

回答by aviran

My Swift 4 version of shouldChangeCharactersIn

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

回答by zheng

update for this Fattie answer

更新此Fattie 答案

thanks

谢谢

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