Używając `textField: shouldChangeCharactersInRange:`, jak uzyskać tekst zawierający aktualnie wpisany znak?

116

Używam poniższego kodu, aby spróbować textField2zaktualizować zawartość tekstową, aby była zgodna textField1, gdy użytkownik wpisze textField1.

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

Jednak wynik, który obserwuję, jest taki, że ...

textField2 to „12”, gdy textField1 to „123”

textField2 to „123”, gdy textField1 to „1234”

... kiedy chcę:

textField2 to „123”, gdy textField1 to „123”

textField2 to „1234”, gdy textField1 to „1234”

Co ja robię źle?

user265961
źródło
8
Przypominam, że zdumiewająco łatwiej jest zawsze używać zdarzenia „Editing Changed” … po prostu przeciągnij je w IB do utworzonej funkcji.
Fattie
Należy zauważyć, że zdarzenie edycji zmiany nie przechwytuje żadnych zdarzeń zmiany tekstu generowanych programowo, np. Autokorekty / autouzupełniania / zamiany tekstu.
shim

Odpowiedzi:

272

-shouldChangeCharactersInRangejest wywoływana, zanim pole tekstowe faktycznie zmieni swój tekst, dlatego otrzymujesz starą wartość tekstową. Aby otrzymać tekst po aktualizacji użyj:

[textField2 setText:[textField1.text stringByReplacingCharactersInRange:range withString:string]];
Vladimir
źródło
15
To prawie zadziałało dla mnie. Jeśli wpisałem znak, zadziałało. Gdybym nacisnął przycisk usuwania, usunąłby dwa znaki. Dla mnie zadziałała następująca sugestia: stackoverflow.com/questions/388237/ ... Zasadniczo przeciągnij i upuść z pola UITextField do swojego kodu (aby utworzyć funkcję), a następnie kliknij prawym przyciskiem myszy pole tekstowe i przeciągnij i przeciągnij upuść z kręgu „Edycja zmieniona” na nową funkcję. (Ech. Czasami tęsknię za Visual Studio ..)
Mike Gledhill
Czuję też, że jest to ważna odpowiedź, ale nie odpowiedź. O najlepszym sposobie osiągnięcia tego, co chcesz, odpowiedział @tomute
Pedro Borges
5
Lub textFiel.text = (textFiel.text as NSString) .stringByReplacingCharactersInRange (range, withString: string) w Swift
maks.
@MikeGledhill Możesz zrobić to samo programowo:[textField addTarget:self action:@selector(textFieldEditingChanged:) forControlEvents:UIControlEventEditingChanged]
Steve Moser
52
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    NSString * searchStr = [textField.text stringByReplacingCharactersInRange:range withString:string];

    NSLog(@"%@",searchStr);
    return YES;
}
btmanikandan
źródło
40

Szybki 3

W oparciu o zaakceptowaną odpowiedź w Swift 3 powinny działać następujące elementy :

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

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

    return true
}

Uwaga

Obie Stringi NSStringmają metody o nazwie replacingCharacters:inRange:withString. Jednak, zgodnie z oczekiwaniami, pierwszy oczekuje wystąpienia Range, podczas gdy drugi oczekuje wystąpienia NSRange. Metoda textFielddelegata używa NSRangewystąpienia, dlatego NSStringw tym przypadku jest to użycie .

focorner
źródło
replacingCharacters Powinien być stringByReplacingCharactersInRange
Alan Scarpa
1
@Alan_s Skopiowałem ten fragment bezpośrednio z mojego projektu Xcode i działał dobrze. Czy używasz Xcode 8.1 z celem na iOS 10.1?
focorner
25

Zamiast używać UITextFieldDelegate, spróbuj użyć zdarzenia „Editing Changed” UITextField.

tomute
źródło
13

W języku Swift (4), bez NSString(czysty jerzyk):

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
}

Jako rozszerzenie:

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
źródło
8

Szybka wersja do tego:

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
źródło
5

To jest kod, którego potrzebujesz,

if ([textField isEqual:self.textField1])
  textField2.text = [textField1.text stringByReplacingCharactersInRange:range withString:string];
Deepak Danduprolu
źródło
1

użyj osłony

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
    }
ober
źródło
0

Moje rozwiązanie polega na użyciu UITextFieldTextDidChangeNotification.

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

Nie zapomnij zadzwonić [[NSNotificationCenter defaultCenter] removeObserver:self];w deallocmetodzie.

Boweidmann
źródło