ios 设置 UITextField 的最大字符长度
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/433337/
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
Set the maximum character length of a UITextField
提问by Domness
How can I set the maximum amount of characters in a UITextField
on the iPhone SDK when I load up a UIView
?
如何设置的字符的最大数量UITextField
的iPhone SDK当我加载了UIView
?
回答by sickp
While the UITextField
class has no max length property, it's relatively simple to get this functionality by setting the text field's delegate
and implementing the following delegate method:
虽然UITextField
该类没有最大长度属性,但通过设置文本字段delegate
并实现以下委托方法来获得此功能相对简单:
Objective-C
目标-C
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
// Prevent crashing undo bug – see note below.
if(range.length + range.location > textField.text.length)
{
return NO;
}
NSUInteger newLength = [textField.text length] + [string length] - range.length;
return newLength <= 25;
}
Swift
迅速
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let currentCharacterCount = textField.text?.count ?? 0
if range.length + range.location > currentCharacterCount {
return false
}
let newLength = currentCharacterCount + string.count - range.length
return newLength <= 25
}
Before the text field changes, the UITextField asks the delegate if the specified text shouldbe changed. The text field has not changed at this point, so we grab it's current length and the string length we're inserting (either through pasting copied text or typing a single character using the keyboard), minus the range length. If this value is too long (more than 25 characters in this example), return NO
to prohibit the change.
在文本字段更改之前, UITextField 会询问委托是否应更改指定的文本。此时文本字段没有改变,所以我们获取它的当前长度和我们插入的字符串长度(通过粘贴复制的文本或使用键盘输入单个字符)减去范围长度。如果这个值太长(本例中超过 25 个字符),返回NO
禁止更改。
When typing in a single character at the end of a text field, the range.location
will be the current field's length, and range.length
will be 0 because we're not replacing/deleting anything. Inserting into the middle of a text field just means a different range.location
, and pasting multiple characters just means string
has more than one character in it.
在文本字段的末尾输入单个字符时,range.location
将是当前字段的长度,并且range.length
为 0,因为我们没有替换/删除任何内容。插入到文本字段的中间只是意味着一个不同的range.location
,而粘贴多个字符只是意味着其中string
有多个字符。
Deleting single characters or cutting multiple characters is specified by a range
with a non-zero length, and an empty string. Replacement is just a range deletion with a non-empty string.
删除单个字符或剪切多个字符由range
具有非零长度和空字符串的 a指定。替换只是带有非空字符串的范围删除。
A note on the crashing "undo" bug
关于崩溃的“撤消”错误的说明
As is mentioned in the comments, there is a bug with UITextField
that can lead to a crash.
正如评论中提到的,有一个UITextField
可能导致崩溃的错误。
If you paste in to the field, but the paste is prevented by your validation implementation, the paste operation is still recorded in the application's undo buffer. If you then fire an undo (by shaking the device and confirming an Undo), the UITextField
will attempt to replace the string it thinksit pasted in to itself with an empty string. This will crash because it never actuallypasted the string in to itself. It will try to replace a part of the string that doesn't exist.
如果您粘贴到字段中,但您的验证实现阻止了粘贴,则粘贴操作仍会记录在应用程序的撤消缓冲区中。如果您随后触发撤消(通过摇动设备并确认撤消),UITextField
它将尝试用空字符串替换它认为粘贴到自身的字符串。这会崩溃,因为它实际上从未将字符串粘贴到自身中。它将尝试替换不存在的字符串的一部分。
Fortunately you can protect the UITextField
from killing itself like this. You just need to ensure that the range it proposes to replace doesexist within its current string. This is what the initial sanity check above does.
幸运的是,您可以保护它UITextField
免于像这样杀死自己。您只需要确保它建议替换的范围确实存在于其当前字符串中。这就是上面的初始健全性检查所做的。
swift 3.0 with copy and paste working fine.
swift 3.0 复制和粘贴工作正常。
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
let str = (textView.text + text)
if str.characters.count <= 10 {
return true
}
textView.text = str.substring(to: str.index(str.startIndex, offsetBy: 10))
return false
}
Hope it's helpful to you.
希望对你有帮助。
回答by frouo
Swift 4
斯威夫特 4
import UIKit
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
}
}
Edit: memory leak issue fixed.
编辑:修复了内存泄漏问题。
回答by Domness
Thank you august! (Post)
谢谢八月!(发布)
This is the code that I ended up with which works:
这是我最终使用的代码:
#define MAX_LENGTH 20
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if (textField.text.length >= MAX_LENGTH && range.length == 0)
{
return NO; // return NO to not change text
}
else
{return YES;}
}
回答by Jmini
To complete Augustanswer, an possible implementation of the proposed function (see UITextField's delegate).
要完成August 的回答,建议函数的可能实现(请参阅UITextField 的委托)。
I did not test domnesscode, but mine do not get stuck if the user reached the limit, and it is compatible with a new string that comes replace a smaller or equal one.
我没有测试domness代码,但是如果用户达到限制,我的不会卡住,并且它与替换较小或相等的新字符串兼容。
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
//limit the size :
int limit = 20;
return !([textField.text length]>limit && [string length] > range.length);
}
回答by August
You can't do this directly - UITextField
has no maxLengthattribute, but you can set the UITextField's
delegate, then use:
您不能直接执行此操作 -UITextField
没有maxLength属性,但您可以设置UITextField's
委托,然后使用:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
回答by Vincent
Often you have multiple input fields with a different length.
通常,您有多个不同长度的输入字段。
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
int allowedLength;
switch(textField.tag) {
case 1:
allowedLength = MAXLENGTHNAME; // triggered for input fields with tag = 1
break;
case 2:
allowedLength = MAXLENGTHADDRESS; // triggered for input fields with tag = 2
break;
default:
allowedLength = MAXLENGTHDEFAULT; // length default when no tag (=0) value =255
break;
}
if (textField.text.length >= allowedLength && range.length == 0) {
return NO; // Change not allowed
} else {
return YES; // Change allowed
}
}
回答by Martin Pilkington
The best way would be to set up a notification on the text changing. In your -awakeFromNib
of your view controller method you'll want:
最好的方法是在文本更改时设置通知。在您-awakeFromNib
的视图控制器方法中,您需要:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(limitTextField:) name:@"UITextFieldTextDidChangeNotification" object:myTextField];
Then in the same class add:
然后在同一个类中添加:
- (void)limitTextField:(NSNotification *)note {
int limit = 20;
if ([[myTextField stringValue] length] > limit) {
[myTextField setStringValue:[[myTextField stringValue] substringToIndex:limit]];
}
}
Then link up the outlet myTextField
to your UITextField
and it will not let you add any more characters after you hit the limit. Be sure to add this to your dealloc method:
然后将插座连接myTextField
到您的插座UITextField
,它不会让您在达到限制后添加更多字符。请务必将此添加到您的 dealloc 方法中:
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"UITextFieldTextDidChangeNotification" object:myTextField];
回答by Jonathan Gurebo
I created thisUITextFieldLimit subclass:
我创建了这个UITextFieldLimit 子类:
- Multiple textfields supported
- Set the text length limit
- Paste prevention
- Displays a label of left characters inside the textfield, get hidden when you stop editing.
- Shake animation when no characters left.
- 支持多个文本字段
- 设置文本长度限制
- 防糊
- 在文本字段内显示左侧字符的标签,停止编辑时隐藏。
- 当没有角色离开时摇动动画。
Grab the UITextFieldLimit.h
and UITextFieldLimit.m
from this GitHub repository:
抓住UITextFieldLimit.h
并UITextFieldLimit.m
从该GitHub的仓库:
https://github.com/JonathanGurebo/UITextFieldLimit
https://github.com/JonathanGurebo/UITextFieldLimit
and begin to test!
并开始测试!
Mark your storyboard-created UITextField and link it to my subclass using the Identity Inspector:
标记您的故事板创建的 UITextField 并使用身份检查器将其链接到我的子类:
Then you can link it to an IBOutlet and set the limit(default is 10).
然后您可以将其链接到 IBOutlet 并设置限制(默认为 10)。
Your ViewController.h file should contain: (if you wan't to modify the setting, like the limit)
你的 ViewController.h 文件应该包含:(如果你不想修改设置,比如限制)
#import "UITextFieldLimit.h"
/.../
@property (weak, nonatomic) IBOutlet UITextFieldLimit *textFieldLimit; // <--Your IBOutlet
Your ViewController.m file should @synthesize textFieldLimit
.
您的 ViewController.m 文件应该是@synthesize textFieldLimit
.
Set the text length limit in your ViewController.m file:
在 ViewController.m 文件中设置文本长度限制:
- (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.
}
Hope the class helps you. Good luck!
希望课对你有帮助。祝你好运!
回答by Nishant
This should be enough to solve the problem (replace 4 by the limit u want). Just make sure to add delegate in IB.
这应该足以解决问题(用你想要的限制替换 4)。只要确保在 IB 中添加委托。
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
return (newString.length<=4);
}
回答by COVID19
Use below extension to set the maximum character length of a UITextField
and UITextView
.
使用下面的扩展名设置 aUITextField
和的最大字符长度UITextView
。
Swift 4.0
斯威夫特 4.0
private var kAssociationKeyMaxLength: Int = 0
private var kAssociationKeyMaxLengthTextView: 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
}
}
UITextView
用户界面文本视图
extension UITextView:UITextViewDelegate {
@IBInspectable var maxLength: Int {
get {
if let length = objc_getAssociatedObject(self, &kAssociationKeyMaxLengthTextView) as? Int {
return length
} else {
return Int.max
}
}
set {
self.delegate = self
objc_setAssociatedObject(self, &kAssociationKeyMaxLengthTextView, 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
}
}
You can set limit below.
您可以在下面设置限制。