Як ChangeCharactersInRange повинен працювати в Swift?


77

Я використовую shouldChangeCharactersInRange як спосіб використання пошуку на льоту.

Однак у мене проблема, shouldChangeCharactersInRange викликається до того, як текстове поле насправді оновиться:

У цілі C я вирішив це, використовуючи нижче:

-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    NSString * searchStr = [textField.text stringByReplacingCharactersInRange:range withString:string];

    return YES;
}

Однак я спробував написати це в Swift:

func textField(textField: UITextField!, shouldChangeCharactersInRange range: NSRange, replacementString string: String!) -> Bool {
    let txtAfterUpdate:NSString = self.projectSearchTxtFld.text as NSString
    txtAfterUpdate.stringByReplacingCharactersInRange(range, withString: string)

    self.callMyMethod(txtAfterUpdate)
    return true
}

Метод все ще викликається до того, як я отримаю значення?

Відповіді:


166

Свіфт 4, Свіфт 5

Цей метод не використовує NSString

// MARK: - UITextFieldDelegate

extension MyViewController: UITextFieldDelegate {
    func textField(_ textField: UITextField,
                   shouldChangeCharactersIn range: NSRange,
                   replacementString string: String) -> Bool {
        if let text = textField.text,
           let textRange = Range(range, in: text) {
           let updatedText = text.replacingCharacters(in: textRange,
                                                       with: string)
           myvalidator(text: updatedText)
        }
        return true
    }
}

Примітка. Будьте обережні, використовуючи захищене текстове поле.


Він додає один зайвий символ під час набору тексту, в чому причина цього ?.
Сагар Даундкар,

@SagarDaundkar опублікуйте свій приклад тексту
В'ячеслав

@PrashantTukadiya Я сказав про це
В'ячеслав

@Vyacheslav шкода Будь-яка робота навколо цього питання мого stackoverflow.com/questions/50266486 / ...
Prashant Tukadiya

@PrashantTukadiya Я вирішив це за допомогою деякої змінної, яка зберігає стан "друкування"
В'ячеслав

74

stringByReplacingCharactersInRange повернути новий рядок, то як щодо:

func textField(textField: UITextField!, shouldChangeCharactersInRange range: NSRange, replacementString string: String!) -> Bool {
    if let text = textField.text as NSString? {
        let txtAfterUpdate = text.replacingCharacters(in: range, with: string)
        self.callMyMethod(txtAfterUpdate)
    }
    return true
}

3
Цікаво, що нам доводиться перетворювати на NSString під час використання із рядком Swift це не працює через різні типи аргументів.
Hola Soy Edu Feliz Navidad

будь-яким способом без використання старого NSString?
Мартін

@Martin Я не думаю, що існує такий, який би був не надто болючим у порівнянні. NSString <> Перетворення рядків є далеко не найгіршим, однак, враховуючи, що вони безкоштовні
мостові

Це не займає більше 2 символів одночасно
Нупур Шарма

2
Не працює на декількох мовах, таких як корейська. Корейське слово не завершується лише додаванням останнього символу. У разі введення "대한민국", txtAfterUpdate буде "대한 민구 ㄱ". FYI для корейців.
Позначте

41

Свіфт 3 і 4

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    let textFieldText: NSString = (textField.text ?? "") as NSString
    let txtAfterUpdate = textFieldText.replacingCharacters(in: range, with: string)
    callMyMethod(txtAfterUpdate)

    return true
}

func textFieldShouldClear(_ textField: UITextField) -> Bool {
    callMyMethod("")
    return true
}

Свіфт 2.2

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    let textFieldText: NSString = textField.text ?? ""
    let txtAfterUpdate = textFieldText.stringByReplacingCharactersInRange(range, withString: string)
    callMyMethod(txtAfterUpdate)

    return true
}

func textFieldShouldClear(textField: UITextField) -> Bool {
    callMyMethod("")
    return true
}

Хоча textField.textвластивість є необов’язковою, її не можна встановити як нуль. Якщо встановити значення рівним нулю, це значення буде порожнім рядком UITextField. У наведеному вище коді саме тому textFieldTextвстановлюється порожній рядок, якщо textField.textдорівнює нулю (через оператор злиття nil ??).

Реалізація textFieldShouldClear(_:)обробляє випадок, коли кнопка очищення текстового поля видно і натискається.


1
Переконайтеся, що textFieldText має значення NSString, інакше це спричинить помилку з діапазоном. На розв’язання у мене пішло кілька хвилин. Ура.
Sharukh Mastan

Чому все ж? Чому ми не можемо використовувати звичайний клас Swift String?
Шанакор,

11

У Swift 3 це буде виглядати так:

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    let text: NSString = (textField.text ?? "") as NSString
    let resultString = text.replacingCharacters(in: range, with: string)

    return true
}

0

Стрімкий 3


Якщо ви хочете попередньо обробити символи, які користувач набрав або вставив, наступне рішення працює як шарм

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

    let strippedString = <change replacements string so it fits your requirement - strip, trim, etc>

    // replace current content with stripped content
    if let replaceStart = textField.position(from: textField.beginningOfDocument, offset: range.location),
        let replaceEnd = textField.position(from: replaceStart, offset: range.length),
        let textRange = textField.textRange(from: replaceStart, to: replaceEnd) {

        textField.replace(textRange, withText: strippedString)
    }
    return false
}

Знайдіть його тут: https://gist.github.com/Blackjacx/2198d86442ec9b9b05c0801f4e392047


чи не перезапише існуючі символи замість того, щоб вставляти їх? мені все ще потрібно спробувати це, але, якщо shouldChangeCharactersInметод викликається до того, як змінено вміст
textField

Так, це правда, але ви вже можете створити новий рядок, який встановлено для текстового поля, коли ви повернетесь trueу цю функцію. В основному ви можете робити те, що хочете, з поточним та новим вмістом текстового поля, плюс ви можете контролювати, чи хочете ви відхилити зміну, плюс ви можете змінити встановлений рядок. Отже, ви тут маєте повний контроль.
blackjacx

0

Ця функція викликається, коли вносяться зміни, але інтерфейс не оновлюється і чекає вашого вибору

Погляньте на повернене значення bool

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool
  • Якщо ви повернетесь true- це означає, що iOS приймає зміни (текст, каретка ...)
  • Якщо ви повернетесь false- це означає, що ви несете відповідальність за всі ці речі

-6

Щоб отримати точний текст у моєму компоненті UITextField у Swift 3.0, я використовував:

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
   let enteredTxt = textField.text! + string
   doSomethingWithTxt(enteredTxt) //some custom method
}

2
а якщо користувач видаляє один символ? Ви повинні використовувати діапазон.
Габріель Массана

2
Що робити, якщо вони редагували символи в середині рядка? Невикористання діапазону є неправильним.
Michael Peterson
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.