Deshabilite autocorrect después de escribir palabras con el prefijo "@" y luego se puede volver a activar cuando se escribe una nueva palabra

En mi text view me gustaría que la autocorrección se deshabilite al escribir palabras que comiencen con "@". El motivo es que tengo un menu de vista de tabla que aparece y sugiere nombres de usuario. Si se selecciona un nombre de usuario, el text actual se reemplaza por un hyperlink . Esta funcionalidad es muy similar a Facebook .

Todo funciona muy bien si la autocorrección está deshabilitada en mi vista de text. Sin embargo, si habilito la autocorrección en mi vista de text, esto se ensucia a veces debido al text sugerido. Aquí está mi código donde bash cambiar la propiedad autocorrect de la vista de text en el protocolo de delegado:

 - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text { if ([text isEqualToString:@"@"]) { // text starts with "@" so we disable autocorrect textView.autocorrectionType = UITextAutocorrectionTypeNo; } else if ([text isEqualToString:@" "]) { // empty space so we reenable autocorrect textView.autocorrectionType = UITextAutocorrectionTypeYes; } return YES; } 

Por la razón que sea, no funciona aunque la propiedad de autocorrección se esté cambiando correctamente. Verifiqué la propiedad autocorrección de vista de text en el depurador y definitivamente está cambiando, pero el comportamiento mientras estoy escribiendo no lo está. La corrección automática nunca se deshabilita cuando es necesario porque el menu de autocorrección aún aparece debajo del text actual:

introduzca la descripción de la imagen aquí

Edit: Lo tengo funcionando. La mejor solución parece ser cambiar su respuesta a otra vista de text que está oculta, establecer las vistas de text originales autocorrectType y luego reasignar la vista de text original como la primera respuesta. Es un poco hack, pero funciona y no hace que el keyboard salte. También es importante verificar la propiedad textViews autocorrectionType actual para evitar asignaciones de respuesta networkingundantes. Muchas gracias a Lyndsey por ayudarme a llegar a la respuesta.

  • (BOOL) textView: (UITextView *) textView shouldChangeTextInRange: (NSRange) range replacementText: (NSString *) text {if ([text isEqualToString: @ "@"] && textView.autocorrectionType! = UITextAutocorrectionTypeNo) {

     // text starts with "@" so we disable autocorrect [self.hiddenTextView becomeFirstResponder]; textView.autocorrectionType = UITextAutocorrectionTypeNo; [textView becomeFirstResponder]; 

    } else if ([text isEqualToString: @ ""] && textView.autocorrectionType! = UITextAutocorrectionTypeYes) {

     // empty space so we reenable autocorrect [self.hiddenTextView becomeFirstResponder]; textView.autocorrectionType = UITextAutocorrectionTypeYes; [textView becomeFirstResponder]; 

    }

    devolver SÍ; }

Encontré una gran respuesta de Engin Kurutepe sobre cómo alternar correctamente la autocorrección.

La solución es muy simple pero no está documentada: solo puede cambiar las properties definidas en el protocolo UITextInputTraits mientras que UITextView en cuestión NO es el primer respondedor.

Entonces en este caso testing:

 - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text { if ([text isEqualToString:@"@"]) { // text starts with "@" so we disable autocorrect [textView resignFirstResponder]; textView.autocorrectionType = UITextAutocorrectionTypeNo; [textView becomeFirstResponder]; } else if ([text isEqualToString:@" "]) { // empty space so we reenable autocorrect [textView resignFirstResponder]; textView.autocorrectionType = UITextAutocorrectionTypeYes; [textView becomeFirstResponder]; } return YES; } 

Editar:

Y aunque la solución es, sin duda, un poco "hack" como usted señaló en los comentarios, el razonamiento que proporcionó Engin no es y podría ser muy legítimo a pesar de que no está debidamente documentado. Por lo tanto, si de hecho es cierto que "solo puede cambiar las properties definidas en el protocolo UITextInputTraits mientras que UITextView en cuestión NO es el primer respondedor", entonces tal vez se vea obligado a usar un "hack" similar al código Publiqué; en cuyo caso, también puede editar el método que desplaza la barra de herramientas en function de las notifications de keyboard recibidas para que su barra de herramientas no cambie si la autocorrección es intermedia. Tal vez trate de usar un bool como "midToggle" y establezca / resignFirstResponder antes de resignFirstResponder y becomeFirstResponder en shouldChangeTextInRange para que la barra de herramientas sepa que permanece estacionario en esos momentos.

Lo tengo funcionando. La mejor solución parece ser cambiar su respuesta a otra vista de text que está oculta, establecer las vistas de text originales autocorrectType y luego reasignar la vista de text original como la primera respuesta. Es un poco hack, pero funciona y no hace que el keyboard salte. También es importante verificar la propiedad textViews autocorrectionType actual para evitar asignaciones de respuesta networkingundantes. Muchas gracias a Lyndsey por ayudarme a llegar a la respuesta.

 - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text { if ([text isEqualToString:@"@"] && textView.autocorrectionType != UITextAutocorrectionTypeNo) { // text starts with "@" so we disable autocorrect [self.hiddenTextView becomeFirstResponder]; textView.autocorrectionType = UITextAutocorrectionTypeNo; [textView becomeFirstResponder]; } else if ([text isEqualToString:@" "] && textView.autocorrectionType != UITextAutocorrectionTypeYes) { // empty space so we reenable autocorrect [self.hiddenTextView becomeFirstResponder]; textView.autocorrectionType = UITextAutocorrectionTypeYes; [textView becomeFirstResponder]; } return YES; } 

Una forma less hack para resolver esto es comprobar si la cadena que está ingresando es la cadena que eligió. Puede establecer una variable para mantener la cadena que seleccionó en didSelectRowInIndexPath. Luego, en el método de delegado de textView, shouldChangeTextInRange verifica si el text de reemploop coincide con la cadena que eligió en didSelectRowAtIndexPath. Si no coincide, entonces devuelve falso.