Usando `textField: shouldChangeCharactersInRange:`, como obtenho o texto incluindo o caractere digitado atualmente?

116

Estou usando o código abaixo para tentar textField2atualizar o conteúdo de texto de para corresponder ao de textField1sempre que o usuário digitar textField1.

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

No entanto, a saída que observo é que ...

textField2 é "12", quando textField1 é "123"

textField2 é "123", quando textField1 é "1234"

... quando o que eu quero é:

textField2 é "123", quando textField1 é "123"

textField2 é "1234", quando textField1 é "1234"

O que estou fazendo de errado?

user265961
fonte
8
Apenas um lembrete de que é extremamente mais fácil usar sempre o evento "Editing Changed" .. basta arrastá-lo no IB para uma função que você criar.
Fattie
Observe que o evento de edição alterado não captura nenhum evento de alteração de texto gerado programaticamente, por exemplo, autocorreção / preenchimento automático / substituição de texto.
shim

Respostas:

272

-shouldChangeCharactersInRangeé chamado antes que o campo de texto realmente mude seu texto, é por isso que você está obtendo um valor de texto antigo. Para obter o texto após a atualização, use:

[textField2 setText:[textField1.text stringByReplacingCharactersInRange:range withString:string]];
Vladimir
fonte
15
Isso quase funcionou para mim. Se eu digitar um caractere, funcionará. Se eu pressionasse o botão Excluir, ele excluiria dois caracteres. Para mim, a seguinte sugestão funcionou: stackoverflow.com/questions/388237/… Basicamente, arraste e solte do UITextField em seu código (para criar uma função), clique com o botão direito do mouse em seu TextField e arraste solte do círculo para "Edição alterada" para sua nova função. (Suspiro. Às vezes sinto falta do Visual Studio ...)
Mike Gledhill
Eu também sinto que esta é uma resposta válida, mas não A resposta. A melhor maneira de realizar o que deseja foi respondida por @tomute
Pedro Borges
5
Ou textFiel.text = (textFiel.text como NSString) .stringByReplacingCharactersInRange (range, withString: string) em Swift
Máximo de
@MikeGledhill Você pode fazer a mesma coisa programaticamente:[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
fonte
40

Swift 3

Com base na resposta aceita, o seguinte deve funcionar no 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
}

Nota

Ambos Stringe NSStringtêm métodos chamados replacingCharacters:inRange:withString. No entanto, como esperado, o primeiro espera uma instância de Range, enquanto o último espera uma instância de NSRange. O textFieldmétodo delegado usa uma NSRangeinstância, portanto, o uso de NSStringneste caso.

focorner
fonte
replacingCharactersdeveria serstringByReplacingCharactersInRange
Alan Scarpa
1
@Alan_s Copiei este snippet diretamente do meu projeto Xcode e estava funcionando bem. Você está usando o Xcode 8.1 com destino ao iOS 10.1?
focorner
25

Em vez de usar o UITextFieldDelegate, tente usar o evento "Editing Changed" de UITextField.

tomuto
fonte
13

Em Swift (4), sem NSString(Swift puro):

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
}

Como uma extensão:

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
fonte
8

Versão rápida para isso:

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
fonte
5

Este é o código que você precisa,

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

usar guarda

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
fonte
0

Minha solução é usar UITextFieldTextDidChangeNotification.

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

Não se esqueça de chamar [[NSNotificationCenter defaultCenter] removeObserver:self];no deallocmétodo.

Boweidmann
fonte