设置UITextField的最大字符长度

当我加载一个UIView时,我如何在iPhone SDK上设置UITextField中的最大字符数?

301684 次浏览

你不能直接这样做——UITextField没有最大长度属性,但你可以设置UITextField's委托,然后使用:

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string

最好的方法是设置文本更改通知。在视图控制器方法的-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];

谢谢你奥古斯特!(帖子)

这是我最终得到的代码:

#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月 answer,建议函数的可能实现(参见UITextField的委托)。

我没有测试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);
}

用cut &粘贴任意长度的字符串,我建议将函数更改为如下内容:

#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类没有max length属性,但通过设置文本字段的delegate并实现以下委托方法来获得此功能相对简单:

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?.count ?? 0
if range.length + range.location > currentCharacterCount {
return false
}
let newLength = currentCharacterCount + string.count - range.length
return newLength <= 25
}

在文本字段更改之前,UITextField会询问委托是否更改了指定的文本应该。此时文本字段还没有改变,所以我们获取它的当前长度和我们插入的字符串长度(通过粘贴复制的文本或使用键盘输入单个字符),减去范围长度。如果这个值太长(在本例中超过25个字符),则返回NO以禁止更改。

当在文本字段的末尾输入单个字符时,range.location将是当前字段的长度,并且range.length将为0,因为我们没有替换/删除任何东西。插入到文本字段中间只意味着不同的range.location,而粘贴多个字符只意味着string中有多个字符。

删除单个字符或删除多个字符由range指定,其长度为非零,且为空字符串。替换只是一个非空字符串的范围删除。

关于崩溃的“撤销”的说明;错误

正如评论中提到的,UITextField有一个错误,可能导致崩溃。

如果粘贴到字段,但验证实现阻止了粘贴,则粘贴操作仍会记录在应用程序的撤销缓冲区中。如果你随后触发撤销(通过摇动设备并确认撤销),UITextField将尝试用一个空字符串替换它自己粘贴到自己的认为字符串。这将会崩溃,因为它从未实际上将字符串粘贴到自己。它将尝试替换字符串中不存在的部分。

幸运的是,你可以保护UITextField不像这样杀死自己。你只需要确保它建议替换的范围存在于它当前的字符串中。这就是上面最初的健全性检查所做的工作。

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
}

希望对你有帮助。

我发现这个方法又快又简单

- (IBAction)backgroundClick:(id)sender {
if (mytext.length <= 7) {
[mytext resignFirstResponder];
} else {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Too Big"
message:@"Please Shorten Name"
delegate:nil
cancelButtonTitle:@"Cancel"
otherButtonTitles:nil];
[alert show];
[alert release];
}
}
使用接口构建器,您可以在任何函数中链接并获得“编辑更改”的事件。 现在你可以检查长度

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


}

我模拟实际的字符串替换,计算未来字符串的长度:

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

这应该足以解决问题(用你想要的极限替换4)。只要确保在IB中添加委托。

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
return (newString.length<=4);
}

通常您有多个长度不同的输入字段。

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

其他答案不处理用户可以从剪贴板粘贴长字符串的情况。如果我粘贴一个很长的字符串,它应该被截断,但显示出来。 在委托中使用这个:

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'


}

这是处理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;
}
}

现在你想要多少字符,只要给值就行了

 - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range   replacementString:(NSString *)string {
NSUInteger newLength = [textField.text length] + [string length] - range.length;
return (newLength > 25) ? NO : YES;
}

把它压缩到一行代码:)

将你的文本视图的委托设置为“self”,然后在你的.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);
}

这段代码负责输入新字符、删除字符、选择字符然后输入或删除、选择字符并剪切、粘贴,以及选择字符并粘贴。

完成了!

< br > < br > < br > < br >


另外,用位操作编写这段代码的另一种很酷的方法是

-(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));
}

上面给出的一些答案的问题是,例如,我有一个文本字段,我必须设置输入15个字符的限制,然后它在输入第15个字符后停止。但是他们不允许删除。那就是删除按钮也不管用了。我也面临着同样的问题。提出了解决方案,如下所示。非常适合我

- (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; 在任何情况下都可以正常工作

我创建了 UITextFieldLimit子类:

  • 支持多个文本框
  • 设置文本长度限制
  • 粘贴的预防
  • 在文本域中显示左字符的标签,当您停止编辑时隐藏。
  • 当没有字符时摇动动画。

从这个GitHub存储库中获取UITextFieldLimit.hUITextFieldLimit.m:

https://github.com/JonathanGurebo/UITextFieldLimit

开始测试吧!

标记你的故事板创建的UITextField,并使用身份检查器链接到我的子类:

身份检查器

然后可以将其链接到IBOutlet并设置限制(默认为10)。


你的ViewController.h文件应该包含:(如果你不想修改设置,比如限制)

#import "UITextFieldLimit.h"


/.../


@property (weak, nonatomic) IBOutlet UITextFieldLimit *textFieldLimit; // <--Your IBOutlet

ViewController。m文件应该@synthesize textFieldLimit. m。


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

希望这门课能帮到你。好运!

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

我们可以像这样设置文本框的范围。

-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range  replacementString:(NSString *)string
{
int setrange = 20;
return !([textField.text length]>setrange && [string length] > range.length);
}

这限制了字符的数量,但也确保您可以粘贴字段,直到最大限制。

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

下面的代码类似于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;
}
}

我已经实现了一个UITextField扩展,以添加一个maxLength属性。

它基于Xcode 6 IBInspectables,所以你可以在接口构建器上设置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

斯威夫特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
}
}

编辑:内存泄漏问题修复。

enter image description here

-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
if (textField.text.length >= 50) {
return NO;
}
return YES;
}

稍微超出了回答原来的问题,并扩展了Frouo的答案,这里有扩展来修剪空白字符串和最大长度,并利用这些字符串扩展来修剪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"

trimAndLimitToMaxLength()可以在UITextFieldDelegate的textFieldDidEndEditing(_:)中使用,这样用户可以输入或粘贴一个比可接受的长度更长的字符串,然后缩短它,而不是仅仅在最大长度上切断输入。在此过程中,我还将设置带有属性的文本样式,以指示超出可接受长度的文本的任何部分(例如,[NSBackgroundColorAttributeName : UIColor.redColor(), NSForegroundColorAttributeName : UIColor.whiteColor(), NSStrikethroughStyleAttributeName : NSNumber(int: 1)]

我已经开源了一个UITextField子类STATextField,它通过它的maxCharacterLength属性提供了这个功能(以及更多)。

使用这段代码在这里RESTRICTED_LENGTH是长度你想限制的文本字段。

   - (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 2.1+

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


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


let newLength = textField.text!.characters.count + string.characters.count - range.length
return newLength <= 25
}

希望能有所帮助

Swift 2.0 +

首先,为这个过程创建一个类。我们称之为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
}


}

现在保存类.....

使用. .

现在转到你的viewController.swift类,并将你的文本字段的outlet设为..

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


}

不要忘记设置文本字段的委托协议/方法。

让我来解释一下……我正在使用我在另一个类中写的字符串的简单扩展过程。现在我只是调用那些扩展方法从另一个类,我需要他们通过添加检查和最大值。

功能……

  1. 它将设置特定文本字段的最大限制。
  2. 它将为特定文本字段设置接受的键的类型。

类型……

containsOnlyCharactersIn //只接受字符。

containsCharactersIn //接受字符组合

doesNotContainsCharactersIn //不接受字符

希望这有助于.... 谢谢. . < / p >

我在Swift中这样做是为了在使用数字垫时限制8个字符。

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
return !(textField.text?.characters.count == MAX_LENGTH && string != "")
}

我必须测试string != ""以允许删除按钮在数字板上工作,否则它将不允许在达到最大值后删除文本字段中的字符。

Xamarin的:

YourTextField.ShouldChangeCharacters =
delegate(UITextField textField, NSRange range, string replacementString)
{
return (range.Location + replacementString.Length) <= 4; // MaxLength == 4
};
在Swift中有< em >通用解决方案< / em >用于设置最大长度。 通过IBInspectable,你可以在Xcode Attribute Inspector.enter image description here

中添加新的属性
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 3版本 //*****这将不工作与Swift 2.x!* * * * * / / < / p > 首先创建一个新的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
}
}

然后你会看到在故事板一个新的字段(最大长度)当你选择任何TextField

如果你还有更多问题,请查看这个链接:http://www.globalnerdy.com/2016/05/18/ios-programming-trick-how-to-use-xcode-to-set-a-text-fields-maximum-length-visual-studio-style/

如果您限制文本计数的目的是确保文本可以适合其他地方的UILabel,那么我会避免使用字符计数。它会因为一些表情符号而崩溃(试图截断一个两倍大小的表情符号可能会导致应用程序崩溃)。这也是一些语言(如日语和汉语)的问题,它们有两步输入过程,简单的计数是行不通的。

我构建了一个UITextField下拉子类(MPC_CharacterLimitedTextField在github上)。你输入预期的输出标签宽度,它将处理所有语言、表情符号和粘贴问题。不管字符数是多少,它只会收获符合标签的完整字符数。项目中有一个演示,所以你可以测试它,看看它是否是你需要的。希望它能帮助到和我一样有输出长度问题的人。

斯威夫特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
}

谢谢你的投票。:)

我想补充一下@sickp给出的答案。

在他的Swift代码中有一个问题,发生在任何多字节文本(例如表情符号)中。Swift中的NSRangeString是不兼容的,所以委托类将它们组合在一起是令人沮丧的。诀窍是简单地将String对象转换为NSString。根据@sickp所写的内容,正确的解决方案实际上是这样的:

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


let currentText = (textField.text as NSString?) ?? NSString()
let currentCharacterCount = currentText.length
if range.length + range.location > currentCharacterCount {
return false
}
let newLength = currentText.replacingCharacters(in: range, with: string).characters.count
return newLength <= 25
}

适用于Swift 3.1或更高版本

首先添加协议UITextFieldDelegate

如:-

class PinCodeViewController: UIViewController, UITextFieldDelegate {
.....
.....
.....


}

之后创建你的UITextField并设置委托

完成经验:-

import UIKit


class PinCodeViewController: UIViewController, UITextFieldDelegate {


let pinCodetextField: UITextField = {
let tf = UITextField()
tf.placeholder = "please enter your pincode"
tf.font = UIFont.systemFont(ofSize: 15)
tf.borderStyle = UITextBorderStyle.roundedRect
tf.autocorrectionType = UITextAutocorrectionType.no
tf.keyboardType = UIKeyboardType.numberPad
tf.clearButtonMode = UITextFieldViewMode.whileEditing;
tf.contentVerticalAlignment = UIControlContentVerticalAlignment.center
return tf
}()




override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(pinCodetextField)
//----- setup your textfield anchor or position where you want to show it-----




// after that
pinCodetextField.delegate = self // setting the delegate


}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
return !(textField.text?.characters.count == 6 && string != "")
} // this is return the maximum characters in textfield
}

我根据@Frouo给出了补充答案。我认为他的回答是最美丽的方式。因为这是一个我们可以重用的通用控件。

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
}


}

斯威夫特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
}

你也可以在斯威夫特4中使用NotificationCenter来做到这一点

NotificationCenter.default.addObserver(self, selector: #selector(self.handleTextChange(recognizer:)), name: NSNotification.Name.UITextFieldTextDidChange, object: yourTextField)


@objc func handleTextChange(recognizer: NSNotification) {
//max length is 50 charater max
let textField = recognizer.object as! UITextField


if((textField.text?.count)! > 50) {
let newString: String? = (textField.text as NSString?)?.substring(to: 50)
textField.text = newString


}
}

使用下面的扩展来设置UITextFieldUITextView的最大字符长度。

斯威夫特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
}
}

你可以在下面设置限制。

enter image description here

这个简单的方法怎么样?它对我来说很好。

extension UITextField {


func  charactersLimit(to:Int) {


if (self.text!.count > to) {
self.deleteBackward()
}
}
}

然后:

someTextField.charactersLimit(to:16)

Swift 4.2和UITextFieldDelegate方法

这适用于我和限制文本字段有一个最大输入8个字符。希望NSRange最终会改变为Range,但现在我很高兴使用NSString从NSRange创建一个范围涉及到处理另一个可选。

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let text = textField.text ?? ""
let nsString = text as NSString
let newText = nsString.replacingCharacters(in: range, with: string)
return newText.count <= 8
}

斯威夫特4.2 +

通过实现 UITextFieldDelegate方法

  1. < p > ViewController:

    class MyViewController: UIViewController {
    
    
    let MAX_LENGTH = 256
    
    
    @IBOutlet weak var myTextField: UITextField!
    
    
    override viewDidLoad() {
    self.myTextField.delegate = self
    }
    }
    
  2. Delegate:

    extension MyViewController: UITextFieldDelegate {
    
    
    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    let userText =  textView.text ?? ""
    var newText = ""
    if range.length > 0 {
    let txt = NSString(string: userText)
    if txt.length > 0 {
    newText = txt.replacingCharacters(in: range, with: text)
    }
    } else {
    newText = userText + text
    }
    return newText.count <= MAX_LENGTH
    }
    
    
    }
    

在Swift 5.2中工作:

 class AngListVC: UIViewController, UITextFieldDelegate {


@IBOutlet weak var angTextField: UITextField!


override func viewDidLoad() {
super.viewDidLoad()
angTextField.delegate = self
angTextField.addTarget(self, action: #selector(textFieldDidChange(_:)), for: .editingChanged)
      

}


func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let userText =  angTextField.text ?? ""
var newText = ""
if range.length > 0 {
let txt = NSString(string: userText)
if txt.length > 0 {
newText = txt.replacingCharacters(in: range, with: "")
}
} else {
newText = userText + ""
}
return newText.count <= 3
}


@objc func textFieldDidChange(_ textField: UITextField) {
print("textFieldDidChange")
}

Swift 5

添加UITextfield的扩展,然后选择一个文本字段并检查属性检查器

private var __maxLengths = [UITextField: Int]()


extension UITextField {
@IBInspectable var maxLength: Int {
get {
guard let l = __maxLengths[self] else {
return 150 // (default int limit)
}
return l
}
set {
__maxLengths[self] = newValue
addTarget(self, action: #selector(setMaxLength), for: .editingChanged)
}
}


@objc func setMaxLength(textField: UITextField) {
let t = textField.text
textField.text = t?.prefix(maxLength).description
}
}

enter image description here