web-dev-qa-db-fra.com

iOS8 Impossible de masquer le bouton d'annulation dans la barre de recherche dans UISearchController

Mon objectif est d'empêcher le bouton d'annulation d'apparaître dans une barre de recherche d'un UISearchController. J'ai commencé avec Le système de recherche de table Apple avec l'exemple de code UISearchController et ai masqué le bouton d'annulation, comme indiqué dans le code ci-dessous. Cependant, lorsque l'utilisateur appuie sur le champ de texte, le bouton d'annulation apparaît toujours. De l'aide?

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

    ...
21
dguastaf

Je pense qu'il y a trois façons d'y parvenir:

  1. Substituez searchDisplayControllerDidBeginSearch et utilisez le code suivant:

searchController.searchBar.showsCancelButton = false

  1. Sous-classe UISearchBar et substituez les layoutSubviews pour changer cette variable lorsque le système tente de le dessiner.

  2. Enregistrez-vous pour la notification au clavier UIKeyboardWillShowNotification et appliquez le code du point 1.

Bien sûr, vous pouvez toujours implémenter votre barre de recherche.

17
nunofmendes

Pour iOS 8 et UISearchController, utilisez cette méthode de délégué à partir de UISearchControllerDelegate:

func didPresentSearchController(searchController: UISearchController) {
  searchController.searchBar.showsCancelButton = false
}

N'oubliez pas de vous définir en tant que délégué: searchController.delegate = self

17
Andrew Robinson

Sous-classe simplement UISearchController & UISearchBar.

class NoCancelButtonSearchController: UISearchController {
    let noCancelButtonSearchBar = NoCancelButtonSearchBar()
    override var searchBar: UISearchBar { return noCancelButtonSearchBar }
}

class NoCancelButtonSearchBar: UISearchBar {
    override func setShowsCancelButton(_ showsCancelButton: Bool, animated: Bool) { /* void */ }
}
10
ma11hew28

Les sous-classes de projet github suivantes, UISearchBar, sont présentées comme solution 2:

https://github.com/mechaman/CustomSearchControllerSwift

De plus, il sous-classe UISearchController pour permettre de placer la barre de recherche ailleurs que dans l'en-tête tableView!

J'espère que cela t'aides.

3
user2253546

C’était la solution la plus simple que je pouvais trouver dans Swift.

Contrôleur de recherche personnalisé:

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

Barre de recherche personnalisée:

class CustomSearchBar: UISearchBar {
    override func setShowsCancelButton(showsCancelButton: Bool, animated: Bool) {
        // do nothing
    }
}

L'élément le plus important de cette opération consistait à ne créer l'objet _searchBar qu'une seule fois dans init et à le créer à l'intérieur de la propriété stockée.

2
Eric Conner

Sous-classe simplement votre UISearchController et procédez comme suit: 

class CustomSearchController: UISearchController {

   override func viewDidLayoutSubviews() {
       super.viewDidLayoutSubviews()
       searchBar.showsCancelButton = false
   }
}

C’était la solution la plus simple que je pouvais trouver pour résoudre le problème du bouton d’annulation clignotant.

2
mc_plectrum

TL; DR: Le sous-classement UISearchBar et la substitution de setShowsCancelButton: et setShowsCancelButton:animated: masquent le bouton d'annulation.

SOLUTION

Je règle active sur NO si la barre de recherche n'est pas le premier répondant (le clavier n'est ni actif ni affiché), puisqu'il s'agit en réalité d'une commande cancel.

Barre de recherche FJ

Le marquage searchController.searchBar.showsCancelButton = NO ne semble pas fonctionner dans iOS 8. Je n'ai pas testé iOS 9.

FJSearchBar.h

Vide, mais placé ici pour être complet.

@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

Voici où vous voulez faire les vrais changements. Je divise la UISearchBarDelegate dans sa propre catégorie car, à mon humble avis, les catégories rendent les classes plus propres et plus faciles à gérer. Si vous souhaitez conserver le délégué dans l'interface/l'implémentation de la classe principale, n'hésitez pas.

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

Quelques pièces à noter:

  1. J'ai mis la barre de recherche et la variable BOOL comme variables privées au lieu de propriétés, car
    • Ils sont plus légers que les propriétés privées.
    • Ils n'ont pas besoin d'être vus ou modifiés par le monde extérieur.
  2. Nous vérifions si la searchBar est le premier intervenant. Si ce n'est pas le cas, nous désactivons le contrôleur de recherche car le texte est vide et nous ne cherchons plus. Si vous (vraiment} _ voulez être sûr, vous pouvez également vous assurer que searchText.length == 0.
  3. searchBar:textDidChange: est appelé avant searchBarShouldBeginEditing:, raison pour laquelle nous l'avons traité dans cet ordre.
  4. Je mets à jour les résultats de la recherche chaque fois que le texte est modifié, mais vous pouvez déplacer le [self.searchResultsUpdater updateSearchResultsForSearchController:self]; vers searchBarSearchButtonClicked: si vous souhaitez que la recherche soit effectuée uniquement lorsque l'utilisateur appuie sur le bouton Search.
1
mikeho

Utilisez UISearchControllerDelegate.

func willPresentSearchController(_ searchController: UISearchController) {

        searchController.searchBar.setValue("", forKey:"_cancelButtonText")
    }
0
A.G

Rapide:

Ce qui suit a fonctionné pour moi, ajouté sous viewDidLoad, parce que je n'ai jamais voulu ce bouton:

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

Assurez-vous d’ajouter l’ID du searchBar dans le storyboard  enter image description here

0
CristianMoisei