¿Cómo mantienes activado el button de cancelar en la barra de búsqueda cuando se descarta el keyboard?

introduzca la descripción de la imagen aquíintroduzca la descripción de la imagen aquí

Estoy tratando de lograr el mismo efecto que la aplicación Contactos de Apple (captura de pantalla izquierda). El button cancelar en UISearchBar está habilitado incluso cuando se descarta el keyboard. Mi aplicación se comporta de manera diferente (captura de pantalla derecha). El button cancelar se desactiva automáticamente cuando se descarta el keyboard. El usuario se ve obligado a tocar el button cancelar una vez para habilitarlo y luego otra vez para activar el rechazo. Esta no es una buena experiencia de usuario. ¿Cómo mantendré siempre activado el button de cancelación como la aplicación de contactos de Apple?

Detalles técnicos:

No UISearchDisplayController debido a algunos requisitos de layout. Esto es solo un UISearchBar con mi propio controller de búsqueda personalizado. El button cancelar se muestra usando [self.searchBar showsCancelButton:YES animated:YES] . El keyboard se descarta utilizando [self.searchBar resignFirstResponder] .

Puede usar la API de time de ejecución para acceder al button de cancelar.

 UIButton *btnCancel = [self.searchBar valueForKey:@"_cancelButton"]; [btnCancel setEnabled:YES]; 

En lo que respecta a su pregunta, no hay forma de habilitar el button de cancelación cuando se descarta el keyboard, como si no hubiera callback como tal.

Desde iOS 7, toda la subvista de UISearchBar tiene un nivel más profundo. Esto debería funcionar:

 for (UIView *subView in searchBar.subviews) { for (UIView *secondLevelSubview in subView.subviews) { if ([view isKindOfClass:[UIButton class]]) { [(UIButton *)view setEnabled:YES]; } } 

Todavía hacky y puede romper fácilmente en la próxima versión de iOS.

Puedes hacer esto:

 - (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar { [self enableCancelButton]; } - (void)enableCancelButton { for (UIView *view in _seachBar.subviews) { if ([view isKindOfClass:[UIButton class]]) { [(UIButton *)view setEnabled:YES]; } } } 

PERO este es un método bastante hack y estoy bastante seguro de que Apple generalmente no ve con buenos ojos y podría llevar a que la aplicación sea rechazada. Por lo que sé, no parece haber otra forma de hacer lo que intentas hacer.

Implemente el siguiente método de delegado searchBarShouldEndEditing en su código. Espero que sea útil.

 (BOOL)searchBarShouldEndEditing:(UISearchBar *)searchBar { [[searchBar valueForKey:@"_cancelButton"] setEnabled:YES]; return YES; } 

Llamar a [self.searchBar resignFirstResponder] hará que el button de cancelar esté deshabilitado. Por lo tanto, siempre debe actualizar el button Cancelar para habilitarlo después de llamarlo.

C objective

 [searchBar resignFirstResponder]; UIButton *cancelButton = (UIButton *)[searchBar valueForKey:@"cancelButton"]; [cancelButton setEnabled:YES]; 

Rápido

 searchBar.resignFirstResponder() if let cancelButton = searchBar.value(forKey: "cancelButton") as? UIButton cancelButton.isEnabled = true } 

En mi experiencia, view.endEditing(true) es el problema. Porque también se llama .resignFirstResponder si hay un UITextField dentro de la vista, que está contenido en UISearchBar.

https://developer.apple.com/reference/uikit/uiview/1619630-enditing

Aquí hay una solución recursiva que está funcionando para mí.

func enableButtons(_ view:UIView) { for subView in view.subviews { enableButtons(subView) } if let buttonView = view as? UIButton { buttonView.isEnabled = true } }