Используя `textField: shouldChangeCharactersInRange:`, как мне получить текст, включая текущий набранный символ?

Я использую приведенный ниже код, чтобы попытаться обновить текстовое содержимое textField2 в соответствии с textField1 всякий раз, когда пользователь вводит textField1.

- (BOOL) textField: (UITextField *)theTextField shouldChangeCharactersInRange: (NSRange)range replacementString: (NSString *)string {    
  if (theTextField == textField1){    
     [textField2 setText:[textField1 text]];    
  }
}

Однако результат, который я наблюдаю, таков ...

textField2 равен «12», когда textField1 равен «123».

textField2 равен «123», когда textField1 равен «1234».

... когда я хочу:

textField2 равен «123», когда textField1 равен «123»

textField2 - «1234», когда textField1 - «1234».

Что я делаю неправильно?


person user265961    schedule 04.02.2010    source источник
comment
Напоминаем, что всегда использовать событие Editing Changed невероятно проще ... просто перетащите его в IB к создаваемой вами функции.   -  person Fattie    schedule 10.12.2013
comment
Обратите внимание, что событие редактирования измененного не фиксирует события изменения текста, сгенерированные программно, например автозамена / автозаполнение / замена текста.   -  person shim    schedule 16.03.2020


Ответы (9)


-shouldChangeCharactersInRange вызывается до того, как текстовое поле фактически изменит свой текст, поэтому вы получаете старое текстовое значение. Чтобы получить текст после обновления, используйте:

[textField2 setText:[textField1.text stringByReplacingCharactersInRange:range withString:string]];
person Vladimir    schedule 04.02.2010
comment
Это почти сработало для меня. Если я набирал символ, это сработало. Если я нажму кнопку удаления, будут удалены два символа. Для меня сработало следующее предложение: stackoverflow.com/questions/388237/ По сути, перетащите'n'drop из UITextField в свой код (чтобы создать функцию), затем щелкните правой кнопкой мыши текстовое поле, и перетащите 'n'drop из круга для редактирования измененных в вашу новую функцию. (Вздох. Иногда я скучаю по Visual Studio ..) - person Mike Gledhill; 12.05.2013
comment
Я также считаю, что это верный ответ, но не ответ. Лучший способ добиться того, что вы хотите, ответил @tomute - person Pedro Borges; 09.09.2014
comment
Или textFiel.text = (textFiel.text как NSString) .stringByReplacingCharactersInRange (range, withString: string) в Swift - person Max; 17.11.2014
comment
@MikeGledhill То же самое можно делать программно: [textField addTarget:self action:@selector(textFieldEditingChanged:) forControlEvents:UIControlEventEditingChanged] - person Steve Moser; 19.06.2017

Swift 3

Основываясь на принятом ответе, в Swift 3 должно работать следующее:

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

    let newString = NSString(string: textField.text!).replacingCharacters(in: range, with: string)

    return true
}

Примечание

И String, и NSString имеют методы, называемые replacingCharacters:inRange:withString. Однако, как и ожидалось, первый ожидает экземпляр Range, а второй ожидает экземпляр NSRange. Метод делегата textField использует экземпляр NSRange, поэтому в данном случае используется NSString.

person focorner    schedule 01.11.2016
comment
replacingCharacters должно быть stringByReplacingCharactersInRange - person Alan Scarpa; 07.11.2016
comment
@Alan_s Я скопировал этот фрагмент прямо из своего проекта Xcode, и он работал нормально. Вы используете Xcode 8.1 с целью iOS 10.1? - person focorner; 07.11.2016

Вместо использования UITextFieldDelegate попробуйте использовать «Редактирование изменено " события UITextField.

person tomute    schedule 04.02.2010

В Swift (4) без NSString (чистый Swift):

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

    if let textFieldString = textField.text, let swtRange = Range(range, in: textFieldString) {

        let fullString = textFieldString.replacingCharacters(in: swtRange, with: string)

        print("FullString: \(fullString)")
    }

    return true
}

В качестве расширения:

extension UITextField {

    func fullTextWith(range: NSRange, replacementString: String) -> String? {

        if let fullSearchString = self.text, let swtRange = Range(range, in: fullSearchString) {

            return fullSearchString.replacingCharacters(in: swtRange, with: replacementString)
        }

        return nil
    }
}

// Usage:

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

    if let textFieldString = textField.fullTextWith(range: range, replacementString: string) {
        print("FullString: \(textFieldString)")
    }

    return true
}
person bauerMusic    schedule 28.06.2018

Версия Swift для него:

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

    if string == " " {
        return false
    }

    let userEnteredString = textField.text

    var newString = (userEnteredString! as NSString).stringByReplacingCharactersInRange(range, withString: string) as NSString

    print(newString)

    return true
}
person ioopl    schedule 20.11.2015

Это код, который вам нужен,

if ([textField isEqual:self.textField1])
  textField2.text = [textField1.text stringByReplacingCharactersInRange:range withString:string];
person Deepak Danduprolu    schedule 04.02.2010

использовать охрану

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
        guard case let textFieldString as NSString = textField.text where
            textFieldString.stringByReplacingCharactersInRange(range, withString: string).length <= maxLength else {
                return false
        }
        return true
    }
person ober    schedule 12.08.2016

Мое решение - использовать UITextFieldTextDidChangeNotification.

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(copyText:) name:UITextFieldTextDidChangeNotification object:nil];

Не забудьте вызвать [[NSNotificationCenter defaultCenter] removeObserver:self]; в dealloc методе.

person boweidmann    schedule 10.01.2014

Если вам нужно заменить текст текстового поля на это, вы можете использовать мое решение (Swift 3): https://gist.github.com/Blackjacx/2198d86442ec9b9b05c0801f4e392047

После замены вы можете просто textField.text получить составленный текст.

person blackjacx    schedule 11.04.2017