设置UITextField的最大字符长度
当我加载一个UIView
时,如何在iPhone SDK上的UITextField
设置最大字符数?
虽然UITextField类没有最大长度属性,但通过设置文本字段的delegate
并实现以下委托方法来获得此function相对简单:
Objective-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; }
迅速
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { let currentCharacterCount = textField.text?.characters.count ?? 0 if (range.length + range.location > currentCharacterCount){ return false } let newLength = currentCharacterCount + string.characters.count - range.length return newLength <= 25 }
在文本字段更改之前,UITextField会询问委托人是否应更改指定的文本。 文本字段在这一点上没有改变,所以我们抓住它的当前长度和我们插入的string长度(通过粘贴复制的文本或使用键盘input单个字符)减去范围长度。 如果此值太长(本例中超过25个字符),则返回NO
以禁止更改。
当在文本字段的末尾input单个字符时, range.location
将是当前字段的长度,而range.length
将为0,因为我们不replace/删除任何内容。 插入到文本字段的中间只意味着不同的range.location
,而粘贴多个字符就意味着string
有多个字符。
删除单个字符或剪切多个字符由具有非零长度的range
和空string指定。 replace只是一个非空string的范围删除。
关于崩溃“撤消”错误的说明
正如在评论中提到的那样, UITextField
有一个可能导致崩溃的错误。
如果您粘贴到该字段,但粘贴由validation实现阻止,则粘贴操作仍会logging在应用程序的撤消缓冲区中。 如果您随后触发撤消(通过晃动设备并确认撤消), UITextField
将尝试用一个空stringreplace它认为粘贴的string。 这将会崩溃,因为它实际上从未将string粘贴到自身。 它会尝试replace不存在的string的一部分。
幸运的是,您可以像这样保护UITextField免于自杀。 你只需要确保它想要replace的范围确实存在于它的当前string中。 以上是最初的完整性检查。
迅速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 }
希望对你有帮助。
谢谢八月! ( 邮政 )
这是我结束了与哪些作品的代码:
#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;} }
要完成8月份的答案,可能实现所提议的function(请参阅UITextField的委托 )。
我没有testingdomness代码,但是如果用户达到了极限,我不会卡住,而且它与新的string兼容,而replace为更小或相等的string。
-(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); }
Swift 3.1
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) } } func checkMaxLength(textField: UITextField) { guard let prospectiveText = self.text, prospectiveText.characters.count > maxLength else { return } let selection = selectedTextRange let maxCharIndex = prospectiveText.index(prospectiveText.startIndex, offsetBy: maxLength) text = prospectiveText.substring(to: maxCharIndex) selectedTextRange = selection } }
Edit2:将checkMaxLength
更改为在达到maxLimit时不删除整个UITextField.text属性,而是截断string并且不允许额外input。 这个更改是基于这个答案的 , 这个答案使用全局数组泄漏。
编辑:修复了内存泄漏问题。
你不能直接这样做 – UITextField
没有maxLength属性,但你可以设置UITextField's
委托,然后使用:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
通常你有多个不同长度的input字段。
- (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 } }
最好的办法是build立一个关于文本更改的通知。 在您的视图控制器方法的-awakeFromNib
,您将需要:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(limitTextField:) name:@"UITextFieldTextDidChangeNotification" object:myTextField];
然后在同一个类中添加:
- (void)limitTextField:(NSNotification *)note { int limit = 20; if ([[myTextField stringValue] length] > limit) { [myTextField setStringValue:[[myTextField stringValue] substringToIndex:limit]]; } }
然后将出口myTextField
到您的UITextField
,并且不会让您在达到限制后添加更多字符。 一定要添加到你的dealloc方法:
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"UITextFieldTextDidChangeNotification" object:myTextField];
我创build了这个 UITextFieldLimit子类:
- 支持多个文本框
- 设置文本长度限制
- 粘贴预防
- 在文本框内显示左侧字符的标签,停止编辑时隐藏。
- 当没有人物离开时摇动animation。
从这个GitHub仓库中获取UITextFieldLimit.h
和UITextFieldLimit.m
:
https://github.com/JonathanGurebo/UITextFieldLimit
并开始testing!
标记您的故事板创build的UITextField并使用Identity Inspector将其链接到我的子类:
然后,您可以将其链接到IBOutlet并设置限制(默认值为10)。
你的ViewController.h文件应该包含:(如果你不想修改设置,如限制)
#import "UITextFieldLimit.h" /.../ @property (weak, nonatomic) IBOutlet UITextFieldLimit *textFieldLimit; // <--Your IBOutlet
您的ViewController.m文件应该@synthesize textFieldLimit
。
在您的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. }
希望class级帮助你。 祝你好运!
这应该是足以解决问题(取代4的限制,你想)。 只要确保在IB中添加委托。
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string]; return (newString.length<=4); }
Swift 3版本// *****这不适用于Swift 2.x! // *****
首先创build一个新的Swift文件:TextFieldMaxLength.swift,然后添加下面的代码:
import UIKit private var maxLengths = [UITextField: Int]() extension UITextField { @IBInspectable var maxLength: Int { get { guard let length = maxLengths[self] else { return Int.max } return length } set { maxLengths[self] = newValue addTarget( self, action: #selector(limitLength), for: UIControlEvents.editingChanged ) } } func limitLength(textField: UITextField) { guard let prospectiveText = textField.text, prospectiveText.characters.count > maxLength else { return } let selection = selectedTextRange let maxCharIndex = prospectiveText.index(prospectiveText.startIndex, offsetBy: maxLength) text = prospectiveText.substring(to: maxCharIndex) selectedTextRange = selection } }
然后当您select任何TextField时,您将在Storyboard中看到一个新的字段(Max Length)
如果您还有其他问题,请查看此链接: http : //www.globalnerdy.com/2016/05/18/ios-programming-trick-how-to-use-xcode-to-set-a-text-fields -最大长度视觉工作室风格/
使用“界面”构build器,您可以在任何function中链接并获取“编辑已更改”的事件。 现在你可以检查一下长度
- (IBAction)onValueChange:(id)sender { NSString *text = nil; int MAX_LENGTH = 20; switch ([sender tag] ) { case 1: { text = myEditField.text; if (MAX_LENGTH < [text length]) { myEditField.text = [text substringToIndex:MAX_LENGTH]; } } break; default: break; } }
我模拟将要发生的实际stringreplace来计算将来的string长度:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string]; if([newString length] > maxLength) return NO; return YES; }
以下代码类似于sickp的答案,但正确处理复制粘贴操作。 如果您尝试粘贴超出限制的文本,则以下代码将截断文本以适应限制,而不是完全拒绝粘贴操作。
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { static const NSUInteger limit = 70; // we limit to 70 characters NSUInteger allowedLength = limit - [textField.text length] + range.length; if (string.length > allowedLength) { if (string.length > 1) { // get at least the part of the new string that fits NSString *limitedString = [string substringToIndex:allowedLength]; NSMutableString *newString = [textField.text mutableCopy]; [newString replaceCharactersInRange:range withString:limitedString]; textField.text = newString; } return NO; } else { return YES; } }
为了使它适用于任何长度的string的剪切和粘贴,我build议将函数改为:
#define MAX_LENGTH 20 - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { NSInteger insertDelta = string.length - range.length; if (textField.text.length + insertDelta > MAX_LENGTH) { return NO; // the new string would be longer than MAX_LENGTH } else { return YES; } }
这是处理UITextField上的最大长度的正确方法,它允许返回键退出,使文本字段成为第一响应者,并在用户达到极限时让用户退格
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { int MAX_LENGHT = 5; if([string isEqualToString:@"\n"]) { [textField resignFirstResponder]; return FALSE; } else if(textField.text.length > MAX_LENGHT-1) { if([string isEqualToString:@""] && range.length == 1) { return TRUE; } else { return FALSE; } } else { return TRUE; } }
有一个通用的解决scheme ,在Swift中设置最大长度。 通过IBInspectable,您可以在Xcode Attribute Inspector中添加新的属性。
import UIKit private var maxLengths = [UITextField: Int]() extension UITextField { @IBInspectable var maxLength: Int { get { guard let length = maxLengths[self] else { return Int.max } return length } set { maxLengths[self] = newValue addTarget( self, action: Selector("limitLength:"), forControlEvents: UIControlEvents.EditingChanged ) } } func limitLength(textField: UITextField) { guard let prospectiveText = textField.text where prospectiveText.characters.count > maxLength else { return } let selection = selectedTextRange text = prospectiveText.substringWithRange( Range<String.Index>(prospectiveText.startIndex ..< prospectiveText.startIndex.advancedBy(maxLength)) ) selectedTextRange = selection } }
Swift 2.0 +
首先为这个过程创build一个类。 让我们把它叫做StringValidator.swift。
然后只需将下面的代码粘贴到里面。
import Foundation extension String { func containsCharactersIn(matchCharacters: String) -> Bool { let characterSet = NSCharacterSet(charactersInString: matchCharacters) return self.rangeOfCharacterFromSet(characterSet) != nil } func containsOnlyCharactersIn(matchCharacters: String) -> Bool { let disallowedCharacterSet = NSCharacterSet(charactersInString: matchCharacters).invertedSet return self.rangeOfCharacterFromSet(disallowedCharacterSet) == nil } func doesNotContainCharactersIn(matchCharacters: String) -> Bool { let characterSet = NSCharacterSet(charactersInString: matchCharacters) return self.rangeOfCharacterFromSet(characterSet) == nil } func isNumeric() -> Bool { let scanner = NSScanner(string: self) scanner.locale = NSLocale.currentLocale() return scanner.scanDecimal(nil) && scanner.atEnd } }
现在保存class…..
用法..
现在转到您的viewController.swift类,并使您的文本字段的网点为..
@IBOutlet weak var contactEntryTxtFld: UITextField! //First textfield @IBOutlet weak var contactEntryTxtFld2: UITextField! //Second textfield
现在转到textfield的shouldChangeCharactersInRange方法,并使用如下所示。
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { if string.characters.count == 0 { return true } let latestText = textField.text ?? "" let checkAbleText = (latestText as NSString).stringByReplacingCharactersInRange(range, withString: string) switch textField { case contactEntryTxtFld: return checkAbleText.containsOnlyCharactersIn("0123456789") && prospectiveText.characters.count <= 5 case contactEntryTxtFld2: return checkAbleText.containsOnlyCharactersIn("0123456789") && prospectiveText.characters.count <= 5 default: return true } }
不要忘记设置文本字段的委托协议/方法。
让我解释一下…我正在使用我在另一个类中写入的string的简单扩展过程。 现在我只需要通过添加检查和最大值来调用另一个需要它们的类的扩展方法。
特征…
- 它将设置一个特定文本字段的最大限制。
- 它将为特定的文本字段设置接受的键的types。
types…
containsOnlyCharactersIn //只接受字符。
containsCharactersIn //接受字符的组合
doesNotContainsCharactersIn //不接受字符
希望这有助于….谢谢..
对于Xamarin:
YourTextField.ShouldChangeCharacters = delegate(UITextField textField, NSRange range, string replacementString) { return (range.Location + replacementString.Length) <= 4; // MaxLength == 4 };
其他答案不处理的情况下,用户可以从剪贴板粘贴一个长的string。 如果我粘贴一个长的string,它应该被截断,但显示。 在你的委托中使用这个:
static const NSUInteger maxNoOfCharacters = 5; -(IBAction)textdidChange:(UITextField * )textField { NSString * text = textField.text; if(text.length > maxNoOfCharacters) { text = [text substringWithRange:NSMakeRange(0, maxNoOfCharacters)]; textField.text = text; } // use 'text' }
把它弄到1行代码:)
设置你的文本视图的委托为“自我”,然后在你的.h和下面的代码中添加<UITextViewDelegate>
.m ….你可以调整数字“7”是任何你想要的最大数量的字符是。
-(BOOL)textView:(UITextView *)a shouldChangeTextInRange:(NSRange)b replacementText:(NSString *)c { return ((a.text.length+c.length<=7)+(c.length<1)+(b.length>=c.length)>0); }
这个代码包括input新的字符,删除字符,select字符,然后打字或删除,select字符和剪切,一般粘贴,select字符和粘贴。
完成!
或者,另一种用位操作编写代码的很酷的方法是
-(BOOL)textView:(UITextView *)a shouldChangeTextInRange:(NSRange)b replacementText:(NSString *)c { return 0^((a.text.length+c.length<=7)+(c.length<1)+(b.length>=c.length)); }
我已经开源了一个UITextField子类, STATextField ,它提供了这个function(以及更多)的maxCharacterLength
属性。
现在有多less人物只要给你价值
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { NSUInteger newLength = [textField.text length] + [string length] - range.length; return (newLength > 25) ? NO : YES; }
在这里使用此代码RESTRICTED_LENGTH是您想限制为textfield的长度。
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { if (textField == nameTF) { int limit = RESTRICTED_LENGTH - 1; return !([textField.text length]>limit && [string length] > range.length); } else { return YES; } return NO; }
使用数字键盘时,我在Swift中使用了8个字符的限制。
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { return !(textField.text?.characters.count == MAX_LENGTH && string != "") }
我不得不testingstring!=“”来允许删除button在数字键盘上工作,否则它将不允许在文本字段达到其最大值之后删除字符。
我已经实现了一个UITextField扩展来为它添加一个maxLength属性。
它基于Xcode 6 IBInspectables,因此您可以在“接口”构build器上设置maxLength限制。
这是实现:
的UITextField + MaxLength.h
#import <UIKit/UIKit.h> @interface UITextField_MaxLength : UITextField<UITextFieldDelegate> @property (nonatomic)IBInspectable int textMaxLength; @end
的UITextField + MaxLength.m
#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
迅速3.0
当你粘贴string超过你的字符限制时,这个代码工作正常。
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 }
感谢您的选票。 🙂
上面给出的一些答案的问题是,例如我有一个文本字段,我必须设置15个字符input的限制,然后停止input第15个字符后。 但是他们不允许删除。 这是删除button也不起作用。 因为我面临同样的问题。 拿出解决scheme,给出下面。 适合我的作品
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { if(textField.tag==6) { if ([textField.text length]<=30) { return YES; } else if([@"" isEqualToString:string]) { textField.text=[textField.text substringToIndex:30 ]; } return NO; } else { return YES; } }
我有一个文本字段,其标签我已经设置“6”,我已经限制最大字符数限制= 30; 在任何情况下工作正常
(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string]; if ([txt_name.text length]>100) { return NO; } return YES; }
这限制了字符的数量,但也要确保可以粘贴到字段中,直到达到最大限制。
- (void)textViewDidChange:(UITextView *)textView { NSString* str = [textView text]; str = [str substringToIndex:MIN(1000,[str length])]; [textView setText:str]; if([str length]==1000) { // show some label that you've reached the limit of 1000 characters } }
稍微回答原来的问题,扩展Frouo的答案,这里是扩展修剪一个空白string和一个最大长度,并利用这些string扩展修剪一个最大长度的UITextField:
// In String_Extensions.swift extension String { func trimmedString() -> String { var trimmedString = self.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()) let components = trimmedString.componentsSeparatedByCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()).filter { count($0) > 0 } return " ".join(components) } func trimmedStringToMaxLength(maxLength: Int) -> String { return trimmedString().substringToIndex(advance(startIndex, min(count(self), maxLength))).trimmedString() } } // In UITextField_Extensions.swift private var maxLengthDictionary = [UITextField : Int]() private var textFieldMaxLength = 20 extension UITextField { @IBInspectable var maxLength: Int { get { if let maxLength = maxLengthDictionary[self] { return maxLength } else { return textFieldMaxLength } } set { maxLengthDictionary[self] = newValue < textFieldMaxLength + 1 ? newValue : textFieldMaxLength } } func trimAndLimitToMaxLength() { text = text.trimmedStringToMaxLength(maxLength) } } let someTextField = UITextField() let someString = " This is a string that is longer than allowable for a text field. " someTextField.text = someString someTextField.trimAndLimitToMaxLength() println(someTextField.text) // Prints "This is a string tha" let anotherTextField = UITextField() anotherTextField.maxLength = 5 anotherTextField.text = someString anotherTextField.trimAndLimitToMaxLength() println(anotherTextField.text) // Prints "This"
可以在UITextFieldDelegate的textFieldDidEndEditing(_:)
使用trimAndLimitToMaxLength()
以便用户可以input或粘贴比可接受的string更长的时间,然后缩短它,而不是在最大长度处切断input。 在这样做,我还将设置属性的文本样式,以指示超出可接受的长度的文本的任何部分(例如[NSBackgroundColorAttributeName : UIColor.redColor(), NSForegroundColorAttributeName : UIColor.whiteColor(), NSStrikethroughStyleAttributeName : NSNumber(int: 1)]