Panjang maksimum UITextField

120

Ketika saya sudah mencoba Bagaimana Anda mengatur jumlah maksimum karakter yang dapat dimasukkan ke dalam UITextField menggunakan swift? , Saya melihat bahwa jika saya menggunakan semua 10 karakter, saya tidak dapat menghapus karakter juga.

Satu-satunya hal yang dapat saya lakukan adalah membatalkan operasi (menghapus semua karakter secara bersamaan).

Adakah yang tahu cara untuk tidak memblokir keyboard (sehingga saya tidak dapat menambahkan huruf / simbol / angka, tetapi saya dapat menggunakan backspace)?

Giorgio Nocera
sumber

Jawaban:

295

Dengan Swift 5 dan iOS 12, coba penerapan textField(_:shouldChangeCharactersIn:replacementString:)metode berikut yang merupakan bagian dari UITextFieldDelegateprotokol:

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
}
  • Bagian terpenting dari kode ini adalah konversi dari range( NSRange) ke rangeOfTextToReplace( Range<String.Index>). Lihat tutorial video ini untuk memahami mengapa konversi ini penting.
  • Untuk membuat kode ini bekerja dengan baik, Anda juga harus mengatur textField's smartInsertDeleteTypenilai UITextSmartInsertDeleteType.no. Ini akan mencegah kemungkinan penyisipan ruang ekstra (yang tidak diinginkan) saat melakukan operasi tempel.

Kode contoh lengkap di bawah ini menunjukkan cara menerapkan textField(_:shouldChangeCharactersIn:replacementString:)di UIViewController:

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
    }

}
Imanou Petit
sumber
Apakah Anda baru saja meletakkan kode ini di kelas pengontrol tampilan? Atau apakah saya harus membuat koneksi?
Isaac Wasserman
Jika seseorang perlu memberikan beberapa syarat .. Anda dapat melakukan seperti ini ... if (textField .isEqual (mobileNumberTextfield)) {guard let text = textField.text else {return true} biarkan newLength = text.characters.count + string.characters.count - range.length return newLength <= limitLength; } kembali benar;
Narasimha Nallamsetty
6
Untuk Swift 4, text.characters.counttidak digunakan lagitext.count
Mohamed Salah
47

Saya melakukannya seperti ini:

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

Kode bekerja untuk saya. Tapi saya bekerja dengan storyboard. Di Storyboard saya menambahkan tindakan untuk bidang teks di pengontrol tampilan saat mengedit diubah .

Martin
sumber
1
countElements telah diubah untuk menghitung di Swift 2, tetapi mengubahnya berhasil untuk saya!
Yohanes
1
Terima kasih, sekarang Anda dapat menggunakan textField.text? .Characters.count sejak countElements telah diubah.
Anibal R.
1
Tks, itu bekerja dengan baik dengan perubahan ini: countElements (textField.text!) Di Swift 2 adalah: textField.text? .Characters.count
kha
33

Pembaruan untuk 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
}
Shan Ye
sumber
15

Tambahkan lebih detail dari jawaban @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()
    }
}
Buah A.Suk
sumber
1
count (textField.text!) memberikan kesalahan. Anda harus menggunakan textField.text! .Characters.count
Regis St-Gelais
1
Terima kasih @ RegisSt-Gelais, Ini sudah jawaban lama, saya memperbaruinya sekarang
Sruit A. Suk
11

Di Swift 4

Batas 10 karakter untuk bidang teks dan memungkinkan untuk menghapus (spasi mundur)

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
    }
Sai kumar Reddy
sumber
8
func checkMaxLength(textField: UITextField!, maxLength: Int) {
        if (textField.text!.characters.count > maxLength) {
            textField.deleteBackward()
        }
}

perubahan kecil untuk iOS 9

Jeremy Andrews
sumber
8

Cepat 3

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
    }
Basil Mariano
sumber
8

Anda dapat memperluas UITextField dan menambahkan @IBInspectableobjek untuk menanganinya:

SWIFT 5

import UIKit
private var __maxLengths = [UITextField: Int]()
extension UITextField {
    @IBInspectable var maxLength: Int {
        get {
            guard let l = __maxLengths[self] else {
                return 150 // (global default-limit. or just, Int.max)
            }
            return l
        }
        set {
            __maxLengths[self] = newValue
            addTarget(self, action: #selector(fix), for: .editingChanged)
        }
    }
    @objc func fix(textField: UITextField) {
        if let t = textField.text {
            textField.text = String(t.prefix(maxLength))
        }
    }
}

dan setelah itu definisikan pada inspektur atribut

masukkan deskripsi gambar di sini

Lihat Swift 4 Jawaban asli

mohsen
sumber
2
Kode yang bagus dan bersih. Tetapi untuk beberapa alasan hal ini menyebabkan perilaku pengeditan yang aneh saat Anda menggunakan emoji. Kursor melompat ke akhir baris setiap kali Anda mencoba mengedit.
Phontaine Judd
5

Jika Anda ingin menimpa huruf terakhir:

let maxLength = 10

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

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

    return true
}
maxwell
sumber
4

Saya memposting solusi menggunakan IBInspectable, sehingga Anda dapat mengubah nilai panjang maksimal baik di pembuat antarmuka atau secara terprogram. Lihat disini

frouo
sumber
3

Anda dapat menggunakan swift 5 atau swift 4 seperti gambar di bawah masukkan deskripsi gambar di sini

  1. Tambahkan textField di View Controller
  2. Hubungkan ke teks ke ViewController
  3. tambahkan kode dalam tampilan ViewController

     class ViewController: UIViewController , UITextFieldDelegate {
    
      @IBOutlet weak var txtName: UITextField!
    
      var maxLen:Int = 8;
    
     override func viewDidLoad() {
        super.viewDidLoad()
    
        txtName.delegate = self
       }
    
     func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    
         if(textField == txtName){
            let currentText = textField.text! + string
            return currentText.count <= maxLen
         }
    
         return true;
       }
    }

Anda dapat mengunduh GitHub dari Sumber Penuh: https://github.com/enamul95/TextFieldMaxLen

Enamul Haque
sumber
1

Waspadalah terhadap bug urung untuk UITextField yang disebutkan dalam posting ini: Setel panjang karakter maksimum dari UITextField

inilah cara Anda memperbaikinya dengan cepat

if(range.length + range.location > count(textField.text)) {
        return false;
}
Horatio
sumber
Jika Anda ingin mendukung emoji dan penggunaan semacam itu: if (range.length + range.location> count (textField.text.utf16)) {return false; }
AlexD
1
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
    }
AG
sumber
1
Saya suka ekstensi Toast UIView :)
Regis St-Gelais
1

Saya telah menggunakan protokol / ekstensi ini di salah satu aplikasi saya, dan ini sedikit lebih mudah dibaca. Saya suka bagaimana ia mengenali ruang belakang dan secara eksplisit memberi tahu Anda ketika karakter adalah spasi mundur.

Beberapa hal yang perlu diperhatikan:

1. Apa pun yang mengimplementasikan, ekstensi protokol ini perlu menentukan batas karakter. Itu biasanya akan menjadi ViewController Anda, tetapi Anda dapat mengimplementasikan batas karakter sebagai properti yang dihitung dan mengembalikan sesuatu yang lain, misalnya batas karakter pada salah satu model Anda.

2. Anda harus memanggil metode ini di dalam metode delegasi shouldChangeCharactersInRange bidang teks Anda. Jika tidak, Anda tidak akan dapat memblokir entri teks dengan mengembalikan false, dll.

3. Anda mungkin ingin mengizinkan karakter spasi mundur lewat. Itu sebabnya saya menambahkan fungsi ekstra untuk mendeteksi ruang belakang. Metode shouldChangeCharacters dapat memeriksanya dan mengembalikan 'true' lebih awal sehingga Anda selalu mengizinkan spasi belakang.

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
    }

}

Jika ada di antara Anda yang tertarik, saya memiliki repo Github di mana saya telah mengambil beberapa perilaku batas karakter ini dan memasukkannya ke dalam kerangka kerja iOS. Ada protokol yang dapat Anda terapkan untuk mendapatkan tampilan batas karakter seperti Twitter yang menunjukkan seberapa jauh Anda telah melampaui batas karakter.

Kerangka CharacterLimited di Github

Theo Bendixson
sumber
1

Karena delegasi adalah hubungan 1-ke-1 dan saya mungkin ingin menggunakannya di tempat lain karena alasan lain, saya ingin membatasi panjang bidang teks dengan menambahkan kode ini dalam pengaturan mereka:

    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)

        }
MQLN
sumber
0

Saya menggunakan ini;

Batasi 3 karakter

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

        if let txt = textField.text {
            let currentText = txt + string
            if currentText.count > 3 {
                return false
            }
            return true
        }
        return true
    }
alicanozkara.dll
sumber
0

Cepat 5

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        let MAX_LENGTH = 4
        let updatedString = (textField.text! as NSString).replacingCharacters(in: range, with: string)
        return updatedString.count <= MAX_LENGTH
    }
TDK
sumber
-3

Anda perlu memeriksa apakah string yang ada ditambah input lebih besar dari 10.

   func textField(textField: UITextField!,shouldChangeCharactersInRange range: NSRange,    replacementString string: String!) -> Bool {
      NSUInteger newLength = textField.text.length + string.length - range.length;
      return !(newLength > 10)
   }
bhzag
sumber
5
Kode Anda salah. 1. Anda harus mendeklarasikan konstanta atau variabel Anda dengan let atau var di Swift (bukan NSUInteger). 2. TextField.text dan string berjenis String. Panjang bukanlah properti / metode String di Swift.
Imanou Petit