web-dev-qa-db-ja.com

最大長UITextField

swiftを使用してUITextFieldに入力できる最大文字数を設定する方法 を試したとき、10文字すべてを使用すると、文字も消去できないことがわかりました。

私ができる唯一のことは、操作をキャンセルすることです(すべての文字を一緒に削除します)。

キーボードをブロックしない方法を知っている人はいますか(他の文字/記号/数字を追加できないが、バックスペースは使用できます)

101
Giorgio Nocera

Swift 5およびiOS 12の場合、UITextFieldDelegateプロトコルの一部である textField(_:shouldChangeCharactersIn:replacementString:) メソッドの次の実装を試してください。

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    guard let textFieldText = textField.text,
        let rangeOfTextToReplace = Range(range, in: textFieldText) else {
            return false
    }
    let substringToReplace = textFieldText[rangeOfTextToReplace]
    let count = textFieldText.count - substringToReplace.count + string.count
    return count <= 10
}
  • このコードの最も重要な部分は、rangeNSRange)からrangeOfTextToReplaceRange<String.Index>)への変換です。この変換が重要である理由を理解するには、この ビデオチュートリアル を参照してください。
  • このコードを適切に機能させるには、textFieldsmartInsertDeleteType 値をUITextSmartInsertDeleteType.noに設定する必要もあります。これにより、貼り付け操作の実行時に(不要な)余分なスペースが挿入される可能性がなくなります。

以下の完全なサンプルコードは、UIViewControllertextField(_:shouldChangeCharactersIn:replacementString:)を実装する方法を示しています。

import UIKit

class ViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet var textField: UITextField! // Link this to a UITextField in Storyboard

    override func viewDidLoad() {
        super.viewDidLoad()

        textField.smartInsertDeleteType = UITextSmartInsertDeleteType.no
        textField.delegate = self
    }

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        guard let textFieldText = textField.text,
            let rangeOfTextToReplace = Range(range, in: textFieldText) else {
                return false
        }
        let substringToReplace = textFieldText[rangeOfTextToReplace]
        let count = textFieldText.count - substringToReplace.count + string.count
        return count <= 10
    }

}
259
Imanou Petit

私はこのようにします:

func checkMaxLength(textField: UITextField!, maxLength: Int) {
    if (countElements(textField.text!) > maxLength) {
        textField.deleteBackward()
    }
}

コードは私のために機能します。しかし、私は絵コンテで作業します。 Storyboardでは、View Controllerのテキストフィールドにediting changedのアクションを追加します。

43
Martin

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

@Martin回答から詳細を追加

// linked your button here
@IBAction func mobileTFChanged(sender: AnyObject) {
    checkMaxLength(sender as! UITextField, maxLength: 10)
}

// linked your button here
@IBAction func citizenTFChanged(sender: AnyObject) {
    checkMaxLength(sender as! UITextField, maxLength: 13)
}

func checkMaxLength(textField: UITextField!, maxLength: Int) {
    // Swift 1.0
    //if (count(textField.text!) > maxLength) {
    //    textField.deleteBackward()
    //}
    // Swift 2.0
    if (textField.text!.characters.count > maxLength) {
        textField.deleteBackward()
    }
}
14
Sruit A.Suk
func checkMaxLength(textField: UITextField!, maxLength: Int) {
        if (textField.text!.characters.count > maxLength) {
            textField.deleteBackward()
        }
}

IOS 9の小さな変更

7
Jeremy Andrews

In Swift 4

テキストフィールドの最大文字数は10文字で、削除を許可します(バックスペース)

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        if textField ==  userNameFTF{
            let char = string.cString(using: String.Encoding.utf8)
            let isBackSpace = strcmp(char, "\\b")
            if isBackSpace == -92 {
                return true
            }
            return textField.text!.count <= 9
        }
        return true
    }
7
Sai kumar Reddy

Swift

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

            let nsString = NSString(string: textField.text!)
            let newText = nsString.replacingCharacters(in: range, with: string)
            return  newText.characters.count <= limitCount
    }
6
Basil Mariano

IBInspectableを使用してソリューションを投稿したため、インターフェイスビルダーまたはプログラムの両方で最大長の値を変更できます。 ここで確認してください

4
frouo

最後の文字を上書きする場合:

let maxLength = 10

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

    if range.location > maxLength - 1 {
        textField.text?.removeLast()
    }

    return true
}
4
maxwell
Here is my version of code. Hope it helps!

    func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
        let invalidCharacters = NSCharacterSet(charactersInString: "0123456789").invertedSet

        if let range = string.rangeOfCharacterFromSet(invalidCharacters, options: nil, range:Range<String.Index>(start: string.startIndex, end: string.endIndex))
        {
            return false
        }

        if (count(textField.text) > 10  && range.length == 0)
        {
            self.view.makeToast(message: "Amount entry is limited to ten digits", duration: 0.5, position: HRToastPositionCenter)
            return false
        }
        else
        {

        }

        return true
    }
1
A.G

デリゲートは1対1の関係であり、他の理由で他の場所で使用したい場合があるため、セットアップ内でこのコードを追加してテキストフィールドの長さを制限したいと思います。

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)!
        setup()
    }

    required override init(frame: CGRect) {
        super.init(frame: frame)
        setup()
    }

    func setup() {

        // your setup...

        setMaxLength()
    }

    let maxLength = 10

    private func setMaxLength() {
            addTarget(self, action: #selector(textfieldChanged(_:)), for: UIControlEvents.editingChanged)
        }

        @objc private func textfieldChanged(_ textField: UITextField) {
            guard let text = text else { return }
            let trimmed = text.characters.prefix(maxLength)
            self.text = String(trimmed)

        }
1
MQLN

私は自分のアプリの1つでこのプロトコル/拡張機能を使用していますが、もう少し読みやすくなっています。バックスペースを認識し、文字がバックスペースであるときに明示的に通知する方法が気に入っています。

考慮すべき事項:

1。このプロトコル拡張を実装するものはすべて、文字制限を指定する必要があります。これは通常、ViewControllerになりますが、計算されたプロパティとして文字制限を実装し、たとえば、文字制限のあなたのモデルの一つ。

2。テキストフィールドのshouldChangeCharactersInRangeデリゲートメソッド内でこのメソッドを呼び出す必要があります。そうしないと、falseを返すなどしてテキストエントリをブロックできなくなります。

。おそらく、バックスペース文字を許可したいでしょう。それが、バックスペースを検出するための追加機能を追加した理由です。 shouldChangeCharactersメソッドはこれを確認し、早い段階で 'true'を返すことができるため、常にバックスペースを許可します。

protocol TextEntryCharacterLimited{
    var characterLimit:Int { get } 
}

extension TextEntryCharacterLimited{

    func charactersInTextField(textField:UITextField, willNotExceedCharacterLimitWithReplacementString string:String, range:NSRange) -> Bool{

        let startingLength = textField.text?.characters.count ?? 0
        let lengthToAdd = string.characters.count
        let lengthToReplace = range.length

        let newLength = startingLength + lengthToAdd - lengthToReplace

        return newLength <= characterLimit

    }

    func stringIsBackspaceWith(string:String, inRange range:NSRange) -> Bool{
        if range.length == 1 && string.characters.count == 0 { return true }
        return false
    }

}

興味のある方はGithubリポジトリを利用して、この文字制限動作の一部を取り上げてiOSフレームワークに入れました。 Twitterのような文字数制限表示を取得するために実装できるプロトコルがあり、文字数制限をどれだけ超えたかを示します。

GithubのCharacterLimited Framework

1
Theo Bendixson

この投稿で言及されたUITextFieldの元に戻すバグに注意してください: ITextFieldの最大文字長を設定

これがSwiftでの修正方法です

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