how - iOS8 No se puede ocultar el botón de cancelar en la barra de búsqueda en UISearchController
searchbar swift 3 (9)
Mi objetivo es evitar que el botón de cancelación aparezca en una barra de búsqueda en un UISearchController. Comencé con la búsqueda de tablas de Apple con el código de muestra UISearchController y oculté el botón de cancelar como se ve en el recorte de código a continuación. Sin embargo, cuando el usuario toca el campo de texto, el botón de cancelar sigue apareciendo. ¿Alguna ayuda?
override func viewDidLoad() {
super.viewDidLoad()
resultsTableController = ResultsTableController()
searchController = UISearchController(searchResultsController: resultsTableController)
searchController.searchResultsUpdater = self
searchController.searchBar.sizeToFit()
tableView.tableHeaderView = searchController.searchBar
searchController.searchBar.delegate = self
//Hide cancel button - added by me
searchController.searchBar.showsCancelButton = false
...
Creo que hay tres maneras de lograrlo:
- Reemplace searchDisplayControllerDidBeginSearch y use el siguiente código:
searchController.searchBar.showsCancelButton = false
Subclase UISearchBar y anule las vistas de diseño para cambiar esa var cuando el sistema intente dibujarla.
Regístrese para la notificación de teclado UIKeyboardWillShowNotification y aplique el código en el punto 1.
Por supuesto siempre puede implementar su barra de búsqueda.
Esta fue la solución más simple que pude encontrar en Swift.
Controlador de búsqueda personalizado:
class CustomSearchController: UISearchController {
var _searchBar: CustomSearchBar
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
self._searchBar = CustomSearchBar()
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
override init(searchResultsController: UIViewController?) {
self._searchBar = CustomSearchBar()
super.init(searchResultsController: searchResultsController)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override var searchBar: UISearchBar {
return self._searchBar
}
}
Barra de búsqueda personalizada:
class CustomSearchBar: UISearchBar {
override func setShowsCancelButton(showsCancelButton: Bool, animated: Bool) {
// do nothing
}
}
La parte más importante de esto fue crear solo el objeto _searchBar
una vez en init
en lugar de crearlo dentro de la propiedad almacenada.
Las siguientes subclases de proyecto github UISearchBar que se presentan como solución 2:
https://github.com/mechaman/CustomSearchControllerSwift
Encima de eso, también sub-clasifica UISearchController para permitir que uno ponga la barra de búsqueda en lugares que no sean el encabezado de tableView.
Espero que esto ayude.
Para iOS 8 y UISearchController, use este método de delegado de UISearchControllerDelegate
:
func didPresentSearchController(searchController: UISearchController) {
searchController.searchBar.showsCancelButton = false
}
No olvides establecerte como delegado: searchController.delegate = self
Simplemente subclase UISearchController
y UISearchBar
.
class NoCancelButtonSearchController: UISearchController {
let noCancelButtonSearchBar = NoCancelButtonSearchBar()
override var searchBar: UISearchBar { return noCancelButtonSearchBar }
}
class NoCancelButtonSearchBar: UISearchBar {
override func setShowsCancelButton(_ showsCancelButton: Bool, animated: Bool) { /* void */ }
}
Subclasifique su UISearchController y haga lo siguiente:
class CustomSearchController: UISearchController {
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
searchBar.showsCancelButton = false
}
}
Esta fue la solución más fácil que se me ocurrió para resolver el problema del botón de cancelar parpadeando.
Utilice UISearchControllerDelegate.
func willPresentSearchController(_ searchController: UISearchController) {
searchController.searchBar.setValue("", forKey:"_cancelButtonText")
}
TL; DR : UISearchBar
y anulando setShowsCancelButton:
y setShowsCancelButton:animated:
oculta el botón cancelar.
SOLUCIÓN
Establecí active
en NO
si la barra de búsqueda no es el primer respondedor (el teclado no está activo y se muestra), ya que efectivamente es un comando de cancelación .
FJSearchBar
Marcar searchController.searchBar.showsCancelButton = NO
no parece funcionar en iOS 8 . No he probado iOS 9 .
FJSearchBar.h
Vacío, pero colocado aquí para la integridad.
@import UIKit;
@interface FJSearchBar : UISearchBar
@end
FJSearchBar.m
#import "FJSearchBar.h"
@implementation FJSearchBar
- (void)setShowsCancelButton:(BOOL)showsCancelButton {
// do nothing
}
- (void)setShowsCancelButton:(BOOL)showsCancelButton animated:(BOOL)animated {
// do nothing
}
@end
FJSearchController
Aquí es donde quieres hacer los cambios reales. UISearchBarDelegate
en su propia categoría porque, en mi humilde opinión, las categorías hacen que las clases sean más limpias y fáciles de mantener. Si desea mantener al delegado dentro de la interfaz / implementación de la clase principal, puede hacerlo.
FJSearchController.h
@import UIKit;
@interface FJSearchController : UISearchController
@end
@interface FJSearchController (UISearchBarDelegate) <UISearchBarDelegate>
@end
FJSearchController.m
#import "FJSearchController.h"
#import "FJSearchBar.h"
@implementation FJSearchController {
@private
FJSearchBar *_searchBar;
BOOL _clearedOutside;
}
- (UISearchBar *)searchBar {
if (_searchBar == nil) {
// if you''re not hiding the cancel button, simply uncomment the line below and delete the FJSearchBar alloc/init
// _searchBar = [[UISearchBar alloc] init];
_searchBar = [[FJSearchBar alloc] init];
_searchBar.delegate = self;
}
return _searchBar;
}
@end
@implementation FJSearchController (UISearchBarDelegate)
- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar {
// if we cleared from outside then we should not allow any new editing
BOOL shouldAllowEditing = !_clearedOutside;
_clearedOutside = NO;
return shouldAllowEditing;
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
// hide the keyboard since the user will no longer add any more input
[searchBar resignFirstResponder];
}
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
if (![searchBar isFirstResponder]) {
// the user cleared the search while not in typing mode, so we should deactivate searching
self.active = NO;
_clearedOutside = YES;
return;
}
// update the search results
[self.searchResultsUpdater updateSearchResultsForSearchController:self];
}
@end
Algunas partes a tener en cuenta:
- He puesto la barra de búsqueda y el
BOOL
como variables privadas en lugar de propiedades porque- Son más ligeros que las propiedades privadas.
- No necesitan ser vistos o modificados por el mundo exterior.
- Verificamos si el
searchBar
es el primer respondedor. Si no lo está, entonces desactivamos el controlador de búsqueda porque el texto está vacío y ya no estamos buscando. Si realmente quiere estar seguro, también puede asegurarse de quesearchText.length == 0
. -
searchBar:textDidChange:
se invoca antes desearchBarShouldBeginEditing:
por lo que lo manejamos en este orden. - Actualizo los resultados de la búsqueda cada vez que cambia el texto, pero es posible que desee mover el
[self.searchResultsUpdater updateSearchResultsForSearchController:self];
tosearchBarSearchButtonClicked:
si solo desea que la búsqueda se realice después de que el usuario presione el botón Buscar .