在文本字段更改之前,UITextField会询问委托是否应更改指定的文本 . 此时文本字段没有改变,所以我们 grab 它's current length and the string length we'重新插入(通过粘贴复制的文本或使用键盘键入单个字符),减去范围长度 . 如果此值太长(在此示例中超过25个字符),请返回 NO 以禁止更改 .
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[textFieldLimit setLimit:25];// <-- and you won't be able to put more than 25 characters in the TextField.
}
#import "UITextField+MaxLength.h"
@interface UITextField_MaxLength()
@property (nonatomic, assign) id <UITextFieldDelegate> superDelegate;
@end
@implementation UITextField_MaxLength
- (BOOL)textField:(UITextField *) textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
//validate the length, only if it's set to a non zero value
if (self.textMaxLength>0) {
if(range.length + range.location > textField.text.length)
return NO;
if (textField.text.length+string.length - range.length>self.textMaxLength) {
return NO;
}
}
//if length validation was passed, query the super class to see if the delegate method is implemented there
if (self.superDelegate && [self.superDelegate respondsToSelector:@selector(textField:shouldChangeCharactersInRange:replacementString:)]) {
return [self.superDelegate textField:textField shouldChangeCharactersInRange:range replacementString:string];
}
else{
//if the super class does not implement the delegate method, simply return YES as the length validation was passed
return YES;
}
}
- (void)setDelegate:(id<UITextFieldDelegate>)delegate {
if (delegate == self)
return;
self.superDelegate = delegate;
[super setDelegate:self];
}
//forward all non overriden delegate methods
- (id)forwardingTargetForSelector:(SEL)aSelector {
if ([self.superDelegate respondsToSelector:aSelector])
return self.superDelegate;
return [super forwardingTargetForSelector:aSelector];
}
- (BOOL)respondsToSelector:(SEL)aSelector {
if ([self.superDelegate respondsToSelector:aSelector])
return YES;
return [super respondsToSelector:aSelector];
}
@end
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)
}
}
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
}
//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
}
}
987
使用以下扩展名为 UITextField 和 UITextView 字符限制 .
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)
addTarget(self, action: #selector(checkMaxLength), for: .editingChanged)
}
}
@objc func checkMaxLength(textField: UITextField) {
guard let prospectiveText = self.text,
prospectiveText.count > maxLength
else {
return
}
let selection = selectedTextRange
let indexEndOfText = prospectiveText.index(prospectiveText.startIndex, offsetBy: maxLength)
let substring = prospectiveText[..<indexEndOfText]
text = String(substring)
selectedTextRange = selection
}
}
extension UITextView:UITextViewDelegate {
@IBInspectable var maxLength: Int {
get {
if let length = objc_getAssociatedObject(self, &kAssociationKeyMaxLength) as? Int {
return length
} else {
return Int.max
}
}
set {
self.delegate = self
objc_setAssociatedObject(self, &kAssociationKeyMaxLength, newValue, .OBJC_ASSOCIATION_RETAIN)
}
}
public func textViewDidChange(_ textView: UITextView) {
checkMaxLength(textField: self)
}
@objc func checkMaxLength(textField: UITextView) {
guard let prospectiveText = self.text,
prospectiveText.count > maxLength
else {
return
}
let selection = selectedTextRange
let indexEndOfText = prospectiveText.index(prospectiveText.startIndex, offsetBy: maxLength)
let substring = prospectiveText[..<indexEndOfText]
text = String(substring)
selectedTextRange = selection
}
}
30 回答
虽然
UITextField
类没有最大长度属性,但是's relatively simple to get this functionality by setting the text field' sdelegate
并实现以下委托方法:Objective-C
Swift
在文本字段更改之前,UITextField会询问委托是否应更改指定的文本 . 此时文本字段没有改变,所以我们 grab 它's current length and the string length we'重新插入(通过粘贴复制的文本或使用键盘键入单个字符),减去范围长度 . 如果此值太长(在此示例中超过25个字符),请返回
NO
以禁止更改 .在文本字段末尾键入单个字符时,
range.location
将是当前字段的长度,range.length
将为0,因为我们不会替换/删除任何内容 . 插入文本字段的中间只是意味着不同的range.location
,粘贴多个字符只意味着string
中有多个字符 .删除单个字符或剪切多个字符由
range
指定,长度为非零,空字符串 . 替换只是一个非空字符串的范围删除 .关于崩溃“撤消”错误的说明
正如评论中提到的,
UITextField
存在一个可能导致崩溃的错误 .如果粘贴到字段中,但验证实现阻止了粘贴,则粘贴操作仍会记录在应用程序的撤消缓冲区中 . 如果然后触发撤消(通过摇动设备并确认撤消),
UITextField
将尝试用空字符串替换它认为粘贴的字符串 . 这会崩溃,因为它从未真正将字符串粘贴到自身 . 它将尝试替换不存在的字符串的一部分 .幸运的是,你可以保护
UITextField
不会像这样自杀 . 您只需要确保它建议替换的范围确实存在于其当前字符串中 . 这是上面的初步健全检查 .swift 3.0,复制和粘贴工作正常 .
希望它对你有所帮助 .
谢谢八月! (Post)
这是我最终使用的代码:
斯威夫特4
编辑:内存泄漏问题已修复 .
要完成 August 回答,可能实现建议的功能(参见UITextField's delegate) .
我没有测试 domness 代码,但是如果用户达到了限制,我不会卡住,并且它与替换较小或相等的新字符串兼容 .
你不能直接这样做 -
UITextField
没有maxLength属性,但你可以设置UITextField's
委托,然后使用:通常,您有多个具有不同长度的输入字段 .
最好的方法是设置文本更改通知 . 在您的视图控制器方法的
-awakeFromNib
中,您需要:然后在同一个类中添加:
然后将插座
myTextField
链接到您的UITextField
,并且在您达到限制后不会再添加任何字符 . 请务必将此添加到您的dealloc方法:我创建了this UITextFieldLimit子类:
支持多个文本字段
设置文本长度限制
粘贴预防
在文本字段内显示左侧字符的标签,在停止编辑时隐藏 .
没有剩下任何字符时摇动动画 .
从这个GitHub存储库中抓取
UITextFieldLimit.h
和UITextFieldLimit.m
:https://github.com/JonathanGurebo/UITextFieldLimit
并开始测试!
标记您的故事板创建的UITextField并使用Identity Inspector将其链接到我的子类:
然后,您可以将其链接到IBOutlet并设置限制(默认值为10) .
您的ViewController.h文件应包含:(如果您不想修改设置,如限制)
您的ViewController.m文件应为
@synthesize textFieldLimit
.在ViewController.m文件中设置文本长度限制:
希望全班同学帮助你 . 祝好运!
这应该足以解决问题(用你想要的限制替换4) . 只需确保在IB中添加委托 .
我模拟了即将发生的实际字符串替换,以计算未来字符串的长度:
Swift 3版本// *****这不适用于Swift 2.x! // *****
首先创建一个新的Swift文件:TextFieldMaxLength.swift,然后添加以下代码:
然后,当您选择任何TextField时,您将在Storyboard中看到一个新字段(Max Length)
如果您还有其他问题,请查看此链接:http://www.globalnerdy.com/2016/05/18/ios-programming-trick-how-to-use-xcode-to-set-a-text-fields-maximum-length-visual-studio-style/
使用“界面”构建器,您可以在任何功能中链接并获取“编辑已更改”的事件 . 现在你可以检查长度
以下代码类似于sickp的答案,但处理正确的复制粘贴操作 . 如果您尝试粘贴长度超过限制的文本,以下代码将截断文本以适应限制,而不是完全拒绝粘贴操作 .
为了使它能够剪切和粘贴任何长度的字符串,我建议将函数更改为:
在Swift中设置最大长度有 generic solution . 通过IBInspectable,您可以在Xcode Attribute Inspector中添加新属性 .
Swift 2.0 +
首先为此过程创建一个类 . 让我们称之为StringValidator.swift .
然后只需在其中粘贴以下代码即可 .
现在保存 class ......
Usage..
现在转到你的viewController.swift类,并将你的textfield的出口作为..
现在转到textfield的shouldChangeCharactersInRange方法并使用如下所示 .
不要忘记设置文本字段的委托协议/方法 .
让我解释一下......我正在使用我在另一个类中编写的字符串的简单扩展过程 . 现在我只是通过添加检查和最大值来从我需要它的另一个类调用这些扩展方法 .
Features...
它将设置特定文本字段的最大限制 .
它将设置特定文本字段的已接受键的类型 .
Types...
containsOnlyCharactersIn //仅接受字符 .
containsCharactersIn //接受字符组合
doesNotContainsCharactersIn //不接受字符
希望这有帮助....谢谢..
swift 3.0
粘贴字符串超过字符限制时,此代码工作正常 .
谢谢你的投票 . :)
这是在UITextField上处理最大长度的正确方法,它允许返回键退出作为第一响应者的文本字段,并在用户达到限制时让用户退格
对于Xamarin:
Swift 4
其他答案不处理用户可以从剪贴板粘贴长字符串的情况 . 如果我粘贴一个长字符串,它应该被截断但显示 . 在你的代表中使用它:
把它归结为1行代码:)
将文本视图的委托设置为"self",然后在.h中添加
<UITextViewDelegate>
以及.m中的以下代码....您可以将数字"7"调整为您想要的最大字符数 .此代码用于键入新字符,删除字符,选择字符然后键入或删除,选择字符和剪切,粘贴,以及选择字符和粘贴 .
完成!
或者,使用位操作编写此代码的另一种很酷的方法是
我开源了一个UITextField子类STATextField,它提供了这个功能(以及更多)的
maxCharacterLength
属性 .现在你想要多少个字符给出值
在此处使用此代码RESTRICTED_LENGTH是您要为textfield限制的长度 .
当我使用数字键盘时,我在Swift中做了8个字符的限制 .
我必须测试字符串!=“”以允许删除按钮在数字键盘上工作,否则它将不允许在文本字段达到其最大值后删除字符 .
我已经实现了一个UITextField扩展来为它添加一个maxLength属性 .
它基于Xcode 6 IBInspectables,因此您可以在“接口”构建器上设置maxLength限制 .
这是实施:
我基于@Frouo给出了补充答案 . 我认为他的回答是最美好的方式 . 因为它是我们可以重复使用的通用控件 .
使用以下扩展名为
UITextField
和UITextView
字符限制 .您可以在下面设置限制 .
上面给出的一些答案的问题是,例如我有一个文本字段,我必须设置15个字符输入的限制,然后在输入第15个字符后停止 . 但他们不允许删除 . 那是删除按钮也不起作用 . 因为我面临同样的问题 . 推出解决方案,给定下面 . 适合我的作品
我有一个文本字段,其标签我设置为“6”,我限制了最大字符数限制= 30;在每种情况下都能正常工作