web-dev-qa-db-ja.com

UITextFieldの最大文字長を設定する

UITextFieldをロードするときにiPhone SDKでUIViewの最大文字数を設定するにはどうすればよいですか?

459
Domness

UITextFieldクラスには最大長プロパティはありませんが、テキストフィールドの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はデリゲートに、指定されたテキストshouldを変更するかどうかを尋ねます。この時点ではテキストフィールドは変更されていないため、現在の長さと挿入する文字列の長さ(コピーしたテキストの貼り付けまたはキーボードを使用した単一文字の入力)から範囲の長さを引いた値を取得します。この値が長すぎる場合(この例では25文字以上)、NOを返し、変更を禁止します。

テキストフィールドの最後に単一の文字を入力すると、range.locationは現在のフィールドの長さになり、range.lengthは0になります。何も置換/削除しないためです。テキストフィールドの中央に挿入すると、異なるrange.locationを意味し、複数の文字を貼り付けると、stringに複数の文字が含まれることを意味します。

単一の文字の削除または複数の文字の切り取りは、長さがゼロ以外のrangeと空の文字列で指定されます。置換は、空ではない文字列での範囲の削除です。

クラッシュする「元に戻す」バグに関するメモ

コメントで言及されているように、クラッシュを引き起こす可能性のあるUITextFieldのバグがあります。

フィールドに貼り付けても、検証の実装によって貼り付けが禁止されている場合、貼り付け操作はアプリケーションの元に戻すバッファーに記録されます。その後、(デバイスを振って元に戻すことを確認することによって)元に戻すを実行すると、UITextFieldは文字列itthinksを置き換えようとします空の文字列で貼り付けられます。文字列を実際に実際に貼り付けたことがないため、これはクラッシュします。存在しない文字列の一部を置き換えようとします。

幸いなことに、UITextFieldがこのように自分自身を殺すのを防ぐことができます。置き換えることを提案する範囲doesが現在の文字列内に存在することを確認する必要があります。これは、上記の最初の健全性チェックが行うことです。

コピーアンドペーストを使用した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
    }

お役に立てば幸いです。

1010
sickp

8月ありがとうございます! ( 投稿

これは私がうまくいったコードです。

#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;}
}
56
Domness

スイフト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

51
frouo

8月答え、提案された関数の可能な実装を完成させるために( 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);
}
21
Jmini

これを直接実行することはできません - UITextFieldにはmaxLength属性はありませんが、UITextField'sデリゲートを設定してから使用することができます。

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

多くの場合、長さの異なる複数の入力フィールドがあります。

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

最善の方法は、テキストの変更に関する通知を設定することです。あなたのView Controllerメソッドのあなたの-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];
12

私は この UITextFieldLimitサブクラスを作成しました:

  • 複数のテキストフィールドをサポート
  • テキストの長さ制限を設定する
  • 貼り付け防止
  • テキストフィールド内に左の文字のラベルを表示します。編集を停止すると非表示になります。
  • キャラクターがなくなったらアニメーションを振る。

このGitHubリポジトリからUITextFieldLimit.hUITextFieldLimit.mを入手してください。

https://github.com/JonathanGurebo/UITextFieldLimit

そしてテストを始めましょう!

ストーリーボードで作成したUITextFieldをマークし、Identity Inspectorを使ってそれを私のサブクラスにリンクします。

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

クラスがあなたを助けることを願っています。がんばろう!

11
Jonathan Gurebo

これは問題を解決するのに十分であるはずです(4をu u limitで置き換えます)。 IBにデリゲートを追加するようにしてください。

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

その将来の文字列の長さを計算するために起こりそうな実際の文字列置換をシミュレートします。

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

Swift 3 version // ***** Swift 2.xでは動作しません。 ***** //

まず新しい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-テキストフィールドを設定する最大長ビジュアルスタジオスタイル/

7
Gilad Brunfman

次のコードは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;
    }
}
6
wroluk

Interface builderを使用すると、あなたは自分の関数のどれかにリンクして "Editing changed"のイベントを取得することができます。今、あなたは長さのチェックを入れることができます

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

}
6
Vishal Kumar

Swiftで最大長を設定するための一般的な解決策があります。 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
    }

}
5
Hiren

任意の長さの文字列のカットアンドペーストで機能させるには、関数を次のように変更することをお勧めします。

#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;
        }
    }
5
Påhl Melin

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クラスに行き、あなたのテキストフィールドのアウトレットをにしてください..

@IBOutlet weak var contactEntryTxtFld: UITextField! //First textfield
@IBOutlet weak var contactEntryTxtFld2: UITextField!   //Second 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 //文字を受け付けない

これが助けになったことを願っています....ありがとう..

3
onCompletion

UITextFieldUITextViewの最大文字長を設定するには、以下の拡張子を使用してください。

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

    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

3
iMHitesh Surani

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
}
3
Shan Ye

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

}
3
Victor Choy

スイフト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
    }

あなたの投票をありがとう。 :)

3
Ilesh

Xamarinの場合:

YourTextField.ShouldChangeCharacters = 
delegate(UITextField textField, NSRange range, string replacementString)
        {
            return (range.Location + replacementString.Length) <= 4; // MaxLength == 4
        };
2
Kedu

これは、UITextFieldで最大長を処理する正しい方法です。最初のレスポンダとしてreturnキーを使ってテキストフィールドを終了し、制限に達したときにユーザーがバックスペースできるようにします。

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

テキスト数を制限する目的が、テキストが他の場所のUILabelに収まるようにすることである場合は、文字数の使用を避けます。それはいくつかの絵文字で故障します(ダブルサイズの絵文字を切り取ろうとすると、おそらくあなたのアプリがクラッシュします)。また、日本語や中国語など、単純な計算ではうまくいかない2段階の入力プロセスがある、一部の言語でも問題になります。

私はUITextFieldドロップインサブクラス(github上の MPC_CharacterLimitedTextField )を作りました。予想される出力ラベル幅を入力すると、すべての言語、絵文字、および貼り付けの問題が処理されます。文字数に関係なく、ラベルに収まるだけの完全文字を取得します。プロジェクトにはデモがあるので、それをテストして必要なものかどうかを確認できます。それが私と同じ長さで同じ問題を抱えていた誰かに役立つことを願っています。

1
Mike Critchley

この単純なアプローチはどうでしょうか。それは私のためにうまく働きます。

extension UITextField {

    func  charactersLimit(to:Int) {

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

その後:

someTextField.charactersLimit(to:16)
1
Joaquin Pereira

数字パッドを使用するとき、私はSwiftで8文字の制限のためにこれをしました。

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

削除ボタンがテンキーで機能するようにするには、文字列!= ""をテストする必要がありました。

1
u84six

値を与えたいだけの文字数

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

私はそれにmaxLengthプロパティを追加するためにUITextField拡張を実装しました。

これはXcode 6 IBInspectablesに基づいているので、Interface Builderで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
1
Lefteris

1行のコードにしてください:)

テキストビューのデリゲートを "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);
}

このコードは、新しい文字の入力、文字の削除、文字の選択と削除、文字の選択と切り取り、一般的な貼り付け、および文字の選択と貼り付けを説明しています。

完了しました。






あるいは、このコードをビット操作で書くためのもう1つのクールな方法は、

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

他の回答は、ユーザーがクリップボードから長い文字列を貼り付けることができるケースを処理しません。長い文字列を貼り付けると、切り捨てられて表示されるはずです。これをデリゲートに使用してください。

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
8suhas

私はUITextFieldサブクラス、 STATextField をオープンソース化しました。これは、そのmaxCharacterLengthname__プロパティでこの機能を提供します。

1
Stunner

ここでこのコードを使用してください。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;

}
1

Swift 4.2とUITextFieldDelegateメソッド

これは私にとってはうまくいき、8文字の最大入力を持つようにテキストフィールドを制限します。 NSRangeが最終的にRangeに変更されることを願っていますが、NSRangeからRangeを作成するには別のオプションを扱う必要があるので、今のところNSStringを使用してうれしいです。

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
}
1
Edward

Swift 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

            }         
        }
1
Pramod More

Swift 4.2 +

UITextFieldDelegateメソッドを実装することにより

...
let MAX_LENGTH = 256
...

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    var newText = ""
    // always zero when we add characted
    if range.length == 0 {
        newText = ((textField.text ?? "") + string).count
    } 
    // delete/cut/copy/paste character(s)
    else if var text = textField.text, let sRange = Range<String.Index>.init(range, in: text) {
        text.removeSubrange(sRange)
        text.insert(contentsOf: string, at: text.index(text.startIndex, offsetBy: range.location))
        newText = text
    }
    return newText.count < MAX_LENGTH
}
0
Pocheshire

@sickpの答えに追加したいと思います。

彼のSwiftコードには、あらゆるマルチバイトテキスト(emojisなど)で発生する問題があります。 NSRangeStringSwiftは互換性がないので、デリゲートクラスがそれらを組み合わせることはイライラすることです。トリックは単にStringオブジェクトをNSStringに変換することです。

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
}
0
Guy Kogus

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 
    }
0
kishu mewara
(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;
}
0
Mubin Shaikh

例えば、私はテキストフィールドがあり、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"に設定しています、そして私はmax char limit = 30を制限しました。どの場合でも問題なく動作します

0
Jasmeet

これにより文字数が制限されますが、最大数までフィールドに貼り付けることもできます。

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

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
}

それが役に立てば幸い

0
ColossalChris

このようにtextfieldの範囲を設定できます。

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

元の質問に答えることと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)]

0
Scott Gardner