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

116

Я использую приведенный ниже код, чтобы попытаться обновить 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»

Что я делаю не так?

user265961
источник
8
Напоминаем, что всегда использовать событие «Редактирование изменений» невероятно проще … просто перетащите его в IB к функции, которую вы делаете.
Fattie
Обратите внимание, что событие редактирования измененного не фиксирует события изменения текста, созданные программно, например, автозамена / автозаполнение / замена текста.
прокладка

Ответы:

272

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

[textField2 setText:[textField1.text stringByReplacingCharactersInRange:range withString:string]];
Владимир
источник
15
У меня это почти сработало. Если я набирал символ, это сработало. Если я нажму кнопку удаления, будут удалены два символа. Для меня сработало следующее предложение: stackoverflow.com/questions/388237/… По сути, перетащите'n'drop из UITextField в свой код (для создания функции), затем щелкните правой кнопкой мыши текстовое поле и перетащите 'n' перетащите из круга "Редактирование изменено" к вашей новой функции. (Вздох. Иногда я скучаю по Visual Studio ..)
Майк Гледхилл
Я также считаю, что это правильный ответ, но не ТОЧНЫЙ. Ответил @tomute
Педро Борхес
5
Или textFiel.text = (textFiel.text как NSString) .stringByReplacingCharactersInRange (range, withString: string) в Swift
Макс,
@MikeGledhill Вы можете сделать то же самое программно:[textField addTarget:self action:@selector(textFieldEditingChanged:) forControlEvents:UIControlEventEditingChanged]
Стив Мозер,
52
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    NSString * searchStr = [textField.text stringByReplacingCharactersInRange:range withString:string];

    NSLog(@"%@",searchStr);
    return YES;
}
btmanikandan
источник
40

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в данном случае используется.

focorner
источник
replacingCharactersдолжно бытьstringByReplacingCharactersInRange
Алан Скарпа
1
@Alan_s Я скопировал этот фрагмент прямо из своего проекта Xcode, и он работал нормально. Вы используете Xcode 8.1 с целью iOS 10.1?
focorner 07
13

В 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
}
bauerMusic
источник
8

Быстрая версия для него:

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
}
ioopl
источник
5

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

if ([textField isEqual:self.textField1])
  textField2.text = [textField1.text stringByReplacingCharactersInRange:range withString:string];
Дипак Дандупролу
источник
1

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

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
    }
обер
источник
0

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

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

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

boweidmann
источник