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?


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]];

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;
}

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.


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


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
}

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
}

5

Este é o código que você precisa,

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

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
    }

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.


Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.