最大长度

当我尝试使用 如何使用迅速设置可以输入到 UITextField 中的最大字符数?时,我发现如果我使用所有10个字符,我就不能删除这个字符。

我唯一能做的就是取消操作(一起删除所有字符)。

是否有人知道如何不阻塞键盘(以便我不能添加其他字母/符号/数字,但我可以使用退格) ?

154390 次浏览

您需要检查现有字符串加上输入是否大于10。

   func textField(textField: UITextField!,shouldChangeCharactersInRange range: NSRange,    replacementString string: String!) -> Bool {
NSUInteger newLength = textField.text.length + string.length - range.length;
return !(newLength > 10)
}

使用 Swift 5和 iOS 12,尝试以下 textField(_:shouldChangeCharactersIn:replacementString:)方法的实现,这是 UITextFieldDelegate协议的一部分:

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
guard let textFieldText = textField.text,
let rangeOfTextToReplace = Range(range, in: textFieldText) else {
return false
}
let substringToReplace = textFieldText[rangeOfTextToReplace]
let count = textFieldText.count - substringToReplace.count + string.count
return count <= 10
}
  • 这段代码最重要的部分是从 range(NSRange)到 rangeOfTextToReplace(Range<String.Index>)的转换。查看此 视频教程以了解为什么这种转换是重要的。
  • 要使这段代码正常工作,还应该将 textFieldsmartInsertDeleteType值设置为 UITextSmartInsertDeleteType.no。这将防止在执行粘贴操作时可能插入(不需要的)额外空间。

下面的完整示例代码展示了如何在 UIViewController中实现 textField(_:shouldChangeCharactersIn:replacementString:):

import UIKit


class ViewController: UIViewController, UITextFieldDelegate {


@IBOutlet var textField: UITextField! // Link this to a UITextField in Storyboard


override func viewDidLoad() {
super.viewDidLoad()


textField.smartInsertDeleteType = UITextSmartInsertDeleteType.no
textField.delegate = self
}


func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
guard let textFieldText = textField.text,
let rangeOfTextToReplace = Range(range, in: textFieldText) else {
return false
}
let substringToReplace = textFieldText[rangeOfTextToReplace]
let count = textFieldText.count - substringToReplace.count + string.count
return count <= 10
}


}

我是这样做的:

func checkMaxLength(textField: UITextField!, maxLength: Int) {
if (countElements(textField.text!) > maxLength) {
textField.deleteBackward()
}
}

密码对我有用。但我是做故事板的。在 Storyboard 中,我为 剪辑变了上的视图控制器中的文本字段添加了一个操作。

我发布了一个解决方案使用 IBInspectable,所以你可以改变最大长度值在 Interface Builder 或程序。看看这里

注意本文中提到的 UITextField 的撤消错误: 设置 UITextField 的最大字符长度

这就是你迅速解决问题的方法

if(range.length + range.location > count(textField.text)) {
return false;
}

从@Martin 的回答中添加更多细节

// linked your button here
@IBAction func mobileTFChanged(sender: AnyObject) {
checkMaxLength(sender as! UITextField, maxLength: 10)
}


// linked your button here
@IBAction func citizenTFChanged(sender: AnyObject) {
checkMaxLength(sender as! UITextField, maxLength: 13)
}


func checkMaxLength(textField: UITextField!, maxLength: Int) {
// swift 1.0
//if (count(textField.text!) > maxLength) {
//    textField.deleteBackward()
//}
// swift 2.0
if (textField.text!.characters.count > maxLength) {
textField.deleteBackward()
}
}
func checkMaxLength(textField: UITextField!, maxLength: Int) {
if (textField.text!.characters.count > maxLength) {
textField.deleteBackward()
}
}

IOS 9的一个小改动

Here is my version of code. Hope it helps!


func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
let invalidCharacters = NSCharacterSet(charactersInString: "0123456789").invertedSet


if let range = string.rangeOfCharacterFromSet(invalidCharacters, options: nil, range:Range<String.Index>(start: string.startIndex, end: string.endIndex))
{
return false
}


if (count(textField.text) > 10  && range.length == 0)
{
self.view.makeToast(message: "Amount entry is limited to ten digits", duration: 0.5, position: HRToastPositionCenter)
return false
}
else
{


}


return true
}

我一直在我的一个应用程序中使用这个协议/扩展,它的可读性更好一些。我喜欢它识别退格并明确告诉你什么时候一个字符是退格。

有些事情需要考虑:

1.无论是什么实现了这个协议扩展,都需要指定一个字符限制。 这通常是 ViewController,但是您可以将字符限制实现为一个计算属性,并返回其他内容,例如在您的某个模型上的字符限制。

2.您需要在文本字段的 should dChangePersontersInRange 委托方法内调用此方法。否则,您将无法通过返回 false 等来阻止文本输入。

3.您可能希望允许退格字符通过。这就是为什么我添加了额外的函数来检测后退空间。您的 should dChangeProperties 方法可以检查这一点,并在早期返回“ true”,因此始终允许使用退格。

protocol TextEntryCharacterLimited{
var characterLimit:Int { get }
}


extension TextEntryCharacterLimited{


func charactersInTextField(textField:UITextField, willNotExceedCharacterLimitWithReplacementString string:String, range:NSRange) -> Bool{


let startingLength = textField.text?.characters.count ?? 0
let lengthToAdd = string.characters.count
let lengthToReplace = range.length


let newLength = startingLength + lengthToAdd - lengthToReplace


return newLength <= characterLimit


}


func stringIsBackspaceWith(string:String, inRange range:NSRange) -> Bool{
if range.length == 1 && string.characters.count == 0 { return true }
return false
}


}

如果你们有兴趣,我有一个 Github 回购,我已经采取了一些这种字符限制行为,并放入一个 iOS 框架。有一个协议,你可以实现一个类似 Twitter 的字符限制显示,显示你已经超出字符限制多远。

Github 上有限字符框架

Swift 3

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


let nsString = NSString(string: textField.text!)
let newText = nsString.replacingCharacters(in: range, with: string)
return  newText.characters.count <= limitCount
}

因为委托是一对一的关系,我可能会因为其他原因而在其他地方使用它,所以我喜欢限制 textfield 长度,在它们的设置中添加以下代码:

    required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
setup()
}


required override init(frame: CGRect) {
super.init(frame: frame)
setup()
}


func setup() {


// your setup...


setMaxLength()
}


let maxLength = 10


private func setMaxLength() {
addTarget(self, action: #selector(textfieldChanged(_:)), for: UIControlEvents.editingChanged)
}


@objc private func textfieldChanged(_ textField: UITextField) {
guard let text = text else { return }
let trimmed = text.characters.prefix(maxLength)
self.text = String(trimmed)


}

Swift 4的更新

 func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
guard let text = textField.text else { return true }
let newLength = text.count + string.count - range.length
return newLength <= 10
}

如果你想覆盖最后一个字母:

let maxLength = 10


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


if range.location > maxLength - 1 {
textField.text?.removeLast()
}


return true
}

在 Swift 4

文本字段限制为10个字符并允许删除(退格)

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if textField ==  userNameFTF{
let char = string.cString(using: String.Encoding.utf8)
let isBackSpace = strcmp(char, "\\b")
if isBackSpace == -92 {
return true
}
return textField.text!.count <= 9
}
return true
}

你可以使用迅速5或迅速4像 图像看起来像下面这样 enter image description here

  1. 在视图控制器中添加 textField
  2. 连接到 ViewController 的文本
  3. 在视图 ViewController 中添加代码

     class ViewController: UIViewController , UITextFieldDelegate {
    
    
    @IBOutlet weak var txtName: UITextField!
    
    
    var maxLen:Int = 8;
    
    
    override func viewDidLoad() {
    super.viewDidLoad()
    
    
    txtName.delegate = self
    }
    
    
    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    
    
    if(textField == txtName){
    let currentText = textField.text! + string
    return currentText.count <= maxLen
    }
    
    
    return true;
    }
    }
    

You can download Full Source form GitHub: https://github.com/enamul95/TextFieldMaxLen

您可以扩展 UITextField 并添加一个 @IBInspectable对象来处理它:

SWIFT 5

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)
}
}
@objc func fix(textField: UITextField) {
if let t = textField.text {
textField.text = String(t.prefix(maxLength))
}
}
}

然后在属性检查器上定义它

enter image description here

参见 Swift 4原创答案

我用这个;

限制3个字符

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


if let txt = textField.text {
let currentText = txt + string
if currentText.count > 3 {
return false
}
return true
}
return true
}

Swift 5

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let MAX_LENGTH = 4
let updatedString = (textField.text! as NSString).replacingCharacters(in: range, with: string)
return updatedString.count <= MAX_LENGTH
}

Swift 5

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if textField == myTextFieldName {
if range.location > 10 {
return false
}
}
return true
}

或者

func textFieldDidChangeSelection(_ textField: UITextField) {
myTextFieldName.text = String(myTextFieldName.text!.prefix(10))
}

这是我的简单答案,在 Swift 5.0中使用 iOS 14 + 和 Xcode 12 + ..。

viewDidLoad()中添加以下选择器:

override func viewDidLoad() {
// Add a target for myTextField, pointing to .editingDidChange
myTextField.addTarget(self, action: #selector(myTextFieldDidChange(_:)), for: .editingChanged)
}

在类的某个地方,您还可以添加一个可选的字符限制:

// Add an optional character limit
let characterLimit = 100

然后在后面的课上,只需要添加这个函数:

@objc func myTextFieldDidChange(_ textField: UITextField) {
textField.text = String(textField.text!.prefix(self.characterLimit))
}

这将限制您的字符要么当您键入,或者当您复制 + 粘贴文本到文本字段。