Як 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.