Використовуючи `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"

Що я роблю неправильно?


8
Просто нагадування: надзвичайно простіше завжди використовувати подію "Редагування змінено" . Просто перетягніть її в IB до функції, яку ви створюєте.
Fattie

Зауважте, що подія, що змінилася редагуванням, не охоплює жодних подій, що змінюються в тексті, породжених програмно, наприклад, автокорекція / автодоповнення / заміна тексту.
шим

Відповіді:


272

-shouldChangeCharactersInRangeназивається, перш ніж текстове поле фактично змінює текст, тому ви отримуєте старе значення тексту. Щоб отримати текст після використання оновлення:

[textField2 setText:[textField1.text stringByReplacingCharactersInRange:range withString:string]];

15
Це майже працювало для мене. Якщо я набрав персонаж, це спрацювало. Якщо я натиснув кнопку видалення, вона видалила б два символи. Для мене спрацювала наступна пропозиція: stackoverflow.com/questions/388237/… В основному, перетягніть з UITextField у свій код (щоб створити функцію), потім клацніть правою кнопкою миші на своєму TextField та перетягніть ' падіння з кола для "Редагування змінено" до вашої нової функції. (Зітхаю. Я інколи пропускаю Visual Studio ..)
Майк Гледхілл

Я також вважаю, що це правильна відповідь, але це не відповідь. Найкращий спосіб досягти того, що ви хочете, відповів @tomute
Педро Борхес

5
Або textFiel.text = (textFiel.text як NSString) .stringByReplacingCharactersInRange (діапазон, 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;
}

40

Швидкий 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в цьому випадку.


replacingCharactersповинно бутиstringByReplacingCharactersInRange
Алан Скарпа

1
@Alan_s Я скопіював цей фрагмент прямо з мого проекту Xcode, і він прекрасно працював. Ви використовуєте Xcode 8.1 з цільовим на iOS 10.1?
focorner


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
}

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
}


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метод.


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