updatesearchresults searchcontroller how for example customize custom bar ios swift ios8 uisearchbar uisearchcontroller

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:

  1. Reemplace searchDisplayControllerDidBeginSearch y use el siguiente código:

searchController.searchBar.showsCancelButton = false

  1. Subclase UISearchBar y anule las vistas de diseño para cambiar esa var cuando el sistema intente dibujarla.

  2. 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") }


Rápido:

Lo siguiente funcionó para mí, agregado en viewDidLoad, porque nunca quise ese botón:

let searchBarStyle = searchBar.value(forKey: "searchField") as? UITextField searchBarStyle?.clearButtonMode = .never

Asegúrese de agregar la ID de la barra de búsqueda en el guión gráfico.


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:

  1. 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.
  2. 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 que searchText.length == 0 .
  3. searchBar:textDidChange: se invoca antes de searchBarShouldBeginEditing: por lo que lo manejamos en este orden.
  4. Actualizo los resultados de la búsqueda cada vez que cambia el texto, pero es posible que desee mover el [self.searchResultsUpdater updateSearchResultsForSearchController:self]; to searchBarSearchButtonClicked: si solo desea que la búsqueda se realice después de que el usuario presione el botón Buscar .