web-dev-qa-db-fra.com

Empêcher un contrôleur UISearchDisplayController de masquer la barre de navigation

Lorsqu'un utilisateur commence à modifier une barre de recherche de UISearchDisplayController, le contrôleur de recherche devient actif et masque la barre de navigation de la vue tout en présentant la vue de table de recherche. Est-il possible d'empêcher une UISearchDisplayController de masquer la barre de navigation sans la réimplémenter?

64
hadronzoo

La nouvelle classe UISearchController introduite avec iOS 8 a une propriété hidesNavigationBarDuringPresentation que vous pouvez définir sur false si vous souhaitez que la barre de navigation reste visible (par défaut, elle reste masquée).

45
René

Je viens juste de déboguer un peu dans UISearchDisplayController et de constater qu'il appelle une méthode privée sur UINavigationController pour masquer la barre de navigation. Cela se produit dans -setActive: animated :. Si vous sous-classez UISearchDisplayController et remplacez cette méthode par le code suivant, vous pouvez empêcher le masquage de navigationBar en simulant son masquage.

- (void)setActive:(BOOL)visible animated:(BOOL)animated;
{
    if(self.active == visible) return;
    [self.searchContentsController.navigationController setNavigationBarHidden:YES animated:NO];
    [super setActive:visible animated:animated];
    [self.searchContentsController.navigationController setNavigationBarHidden:NO animated:NO];
    if (visible) {
        [self.searchBar becomeFirstResponder];
    } else {
        [self.searchBar resignFirstResponder];
    }   
}

Faites-moi savoir si cela fonctionne pour vous. J'espère aussi que cela ne se cassera pas dans les futures versions d'iOS ... Testé sur iOS 4.0 uniquement.

60
stigi

La solution la plus simple et sans hacks. 

@interface MySearchDisplayController : UISearchDisplayController

@end

@implementation MySearchDisplayController

- (void)setActive:(BOOL)visible animated:(BOOL)animated
{
    [super setActive: visible animated: animated];

    [self.searchContentsController.navigationController setNavigationBarHidden: NO animated: NO];
}

@end
52
Pavel Sharanda

Les réponses ci-dessus ne fonctionnaient pas bien pour moi. Ma solution consiste à faire croire à UISearchDisplayController qu’il n’existait pas de UINavigationController.

Dans votre contrôleur de vue, ajoutez cette méthode

- (UINavigationController *)navigationController {
    return nil;
}

Cela n'a pas eu d'effets secondaires indésirables pour moi, bien que cela semble être une très mauvaise idée ... Si vous devez accéder au contrôleur de navigation, utilisez [super navigationController].

28
joerick

Depuis iOS 8.0, le même comportement peut être obtenu en définissant la propriété self.searchController.hidesNavigationBarDuringPresentation de UISearchController sur False. 

Le code dans Swift ressemble à ceci:

searchController.hidesNavigationBarDuringPresentation = false
10
Peter Ivanics

Essayé cela d'une manière différente, sans sous-classe UISearchDisplayController. Dans votre classe UIViewController où vous définissez le délégué pour UISearchDisplayController, implémentez searchDisplayControllerDidBeginSearch: et ajoutez use 

[self.navigationController setNavigationBarHidden:NO animated:YES];

A fait le tour pour moi, espérons que cela aide.

9
ah335

Je me suis heurté à cela tout en abordant un problème légèrement différent. Lors de l’utilisation de UISearchDisplayController, je souhaite que la barre de recherche soit in la barre de navigation (pas sous).

Il n'est pas difficile de placer la barre de recherche dans la barre de navigation (voir UISearchBar et UINavigationItem ). Cependant, UISearchDisplayController suppose que la barre de recherche est toujours sous la barre de navigation et insiste (comme indiqué ci-après) sur le fait de masquer la barre de navigation lors de la saisie du mot recherche pour que les choses soient terribles. De plus, UISearchDisplayController rend la barre de recherche plus claire que la normale.

J'ai trouvé une solution. L'astuce consiste à libérer UISearchDisplayController (de manière contre-intuitive) du contrôle de toute barre UISearchBar. Si vous utilisez xibs, cela signifie la suppression de l’instance de la barre de recherche ou au moins le décrochage de la prise. Ensuite, créez votre propre UISearchBar:

- (void)viewDidLoad
{
    [super viewDidLoad];

    UISearchBar *searchBar = [[[UISearchBar alloc] init] autorelease];
    [searchBar sizeToFit]; // standard size
    searchBar.delegate = self;

    // Add search bar to navigation bar
    self.navigationItem.titleView = searchBar;
}

Vous devez activer manuellement le contrôleur d'affichage de la recherche lorsque l'utilisateur appuie sur la barre de recherche (en -searchBarShouldBeginEditing:) et le fermer manuellement lorsque l'utilisateur termine la recherche (en -searchDisplayControllerWillEndSearch:). 

#pragma mark <UISearchBarDelegate>

- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar {
    // Manually activate search mode
    // Use animated=NO so we'll be able to immediately un-hide it again
    [self.searchDisplayController setActive:YES animated:NO];

    // Hand over control to UISearchDisplayController during the search
    searchBar.delegate = (id <UISearchBarDelegate>)self.searchDisplayController;

    return YES;
}

#pragma mark <UISearchDisplayDelegate>

- (void) searchDisplayControllerDidBeginSearch:(UISearchDisplayController
*)controller {
    // Un-hide the navigation bar that UISearchDisplayController hid
    [self.navigationController setNavigationBarHidden:NO animated:NO];
}

- (void) searchDisplayControllerWillEndSearch:(UISearchDisplayController
*)controller {
    UISearchBar *searchBar = (UISearchBar *)self.navigationItem.titleView;

    // Manually resign search mode
    [searchBar resignFirstResponder];

    // Take back control of the search bar
    searchBar.delegate = self;
}
4
jrc

iOS 7 bousille un peu les choses ... pour moi cela fonctionnait parfaitement:

/**
 *  Overwrite the `setActive:animated:` method to make sure the UINavigationBar 
 *  does not get hidden and the SearchBar does not add space for the statusbar height.
 *
 *  @param visible   `YES` to display the search interface if it is not already displayed; NO to hide the search interface if it is currently displayed.
 *  @param animated  `YES` to use animation for a change in visible state, otherwise NO.
 */
- (void)setActive:(BOOL)visible animated:(BOOL)animated
{
    [[UIApplication sharedApplication] setStatusBarHidden:YES];
    [self.searchContentsController.navigationController setNavigationBarHidden:YES animated:NO];

    [super setActive:visible animated:animated];

    [self.searchContentsController.navigationController setNavigationBarHidden:NO animated:NO];
    [[UIApplication sharedApplication] setStatusBarHidden:NO];
}

La raison pour afficher/masquer la barre d'état 

3
Paul Peelen

Vraiment belle solution, mais mon application était en panne sous iOS6. J'ai dû faire la modification suivante pour que cela fonctionne.

@implementation ICSearchDisplayController

    - (void)setActive:(BOOL)visible animated:(BOOL)animated
    {
        if (visible == YES) {
            [super setActive:visible animated:animated];
            [self.searchContentsController.navigationController setNavigationBarHidden:NO animated:NO];
        } else {
            [super setActive:NO animated:NO];
        }
    }
3
John Salerno

Cela semble le résoudre pour moi. Testé sous iOS5/6.1. Aucun problème visuel que je pouvais voir.

- (void)viewDidAppear
{
    [super viewDidAppear];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillAppear:) name:UIKeyboardWillShowNotification object:nil];
}

-(void)viewWillDisappear:(BOOL)animated{
    [super viewWillDisappear:animated];
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)keyboardWillAppear:(NSNotification *)notification
{
    [self.navigationController setNavigationBarHidden:NO animated:NO];
}

-(void)viewDidLayoutSubviews{
    [self.navigationController setNavigationBarHidden:NO animated:NO];
}
3
Daniel Ryan

Je pense que la meilleure solution consiste à implémenter UISearchDisplayController vous-même.

Ce n'est pas si difficile. Vous devez seulement implémenter UISearchBarDelegate pour votre UIViewController et inclure un UITableView pour afficher vos résultats de recherche.

1
frankli

J'ajoutais une barre de navigation personnalisée sur mon ViewController qui devenait cachée lors de la recherche; une solution rapide, mais pas si bonne, était 

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText{
    [self.view addSubview:_navBar];
}

_navBar est UINavigationBar ajouté par programme, ce qui m'a aidé à me cacher de la barre de navigation.

0
sahiljain

Comme l'a souligné jrc, "dissocier UISearchDisplayController de tout contrôle UISearchBar" semble fonctionner pour moi. Si je passe nil en tant que paramètre lors de la création de UISearchDisplayController, la barre de navigation reste visible à tout moment:

searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:nil contentsController:self];
0
Dasha Salo

@ Pavel fonctionne parfaitement bien. Cependant, j'essayais de placer cela dans un UIPopoverController et le texte du champ est légèrement poussé lorsque le champ de texte de la barre de recherche devient le premier répondeur. Cela semble un peu moche. Je l'ai donc corrigé en appelant la méthode super avec .animated mis à NO.

0
XCool

Je voulais juste ajouter à Stigi réponse. Lorsque vous annulez la recherche et recommencez la recherche - le tableau des résultats de la recherche ne réagira pas au toucher. Vous devez donc ajouter la ligne suivante. 

self.searchResultsTableView.alpha = 1;

Donc, le code mis à jour ressemble à la suivante

 - (void)setActive:(BOOL)visible animated:(BOOL)animated;
 {
    if(self.active == visible) return;
    if (visible) {
        [self.searchContentsController.navigationController setNavigationBarHidden:YES animated:NO];
        [super setActive:visible animated:animated];
        [self.searchContentsController.navigationController setNavigationBarHidden:NO animated:NO];
        self.searchResultsTableView.alpha = 1;
        [self.searchBar becomeFirstResponder];
    } else {
        [super setActive:visible animated:animated];
        [self.searchBar resignFirstResponder];
    }
}
0
alex1704