Question

Je l'ai mis en place un UISearchBar en vue de la table et presque tout fonctionne sauf une petite chose: Quand j'entrer du texte, puis appuyez sur le bouton de recherche sur le clavier, le clavier disparaît, les résultats de la recherche sont les seuls éléments affichés dans la table, les séjours de texte dans le UISearchBar, mais le bouton annuler obtient désactivé.

Je suis en train de faire ma liste aussi proche de la fonctionnalité des contacts d'Apple App et lorsque vous appuyez sur la recherche dans cette application, il ne désactive pas le bouton d'annulation.

Quand je regarde dans le fichier d'en-tête UISearchBar, je remarque un drapeau pour autoDisableCancelButton sous la struct _searchBarFlags mais il est privé.

Y at-il quelque chose que je manque quand je configurer le UISearchBar?

Était-ce utile?

La solution

J'ai trouvé une solution. Vous pouvez l'utiliser pour la boucle en boucle sur les sous-vues de la barre de recherche et de l'activer lorsque le bouton de recherche est appuyé sur le clavier.

for (UIView *possibleButton in searchBar.subviews)
{
    if ([possibleButton isKindOfClass:[UIButton class]])
    {
        UIButton *cancelButton = (UIButton*)possibleButton;
        cancelButton.enabled = YES;
        break;
    }
}

Autres conseils

Je devais modifier ce un peu pour le faire fonctionner pour moi dans iOS 7

- (void)enableCancelButton:(UISearchBar *)searchBar
{
    for (UIView *view in searchBar.subviews)
    {
        for (id subview in view.subviews)
        {
            if ( [subview isKindOfClass:[UIButton class]] )
            {
                [subview setEnabled:YES];
                NSLog(@"enableCancelButton");
                return;
            }
        }
    }
}

Il y a deux façons d'y parvenir facilement

- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar{
    //  The small and dirty
    [(UIButton*)[searchBar valueForKey:@"_cancelButton"] setEnabled:YES];

    // The long and safe
     UIButton *cancelButton = [searchBar valueForKey:@"_cancelButton"];
    if ([cancelButton respondsToSelector:@selector(setEnabled:)]) {
         cancelButton.enabled = YES;
    }
}

Vous devriez aller avec le second, il ne plantera pas votre demande si Apple va changer en arrière-plan.

BTW je l'ai testé d'iOS 4.0 à 8.2 aucun changement, je l'utilise aussi dans ma demande approuvée de magasin sans aucun problème.

est ce qui fait de travailler sur iOS 6 pour moi:

searchBar.showsCancelButton = YES;
searchBar.showsScopeBar = YES;
[searchBar sizeToFit];
[searchBar setShowsCancelButton:YES animated:YES];

Voici ma solution, qui fonctionne pour toutes les situations dans toutes les versions d'iOS.

IE, d'autres solutions ne gère pas lorsque le clavier se rejetée parce que l'utilisateur fait glisser une vue de défilement.

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

// This will handle whenever the text field is resigned non-programatically
// (IE, because it's set to resign when the scroll view is dragged in your storyboard.)
- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar {
    [self performSelector:@selector(enableCancelButton:) withObject:searchBar afterDelay:0.001];
}

// Also follow up every [searchBar resignFirstResponder];
// with [self enableCancelButton:searchBar];

Aucune des réponses a fonctionné pour moi du tout. Je cible iOS 7. Mais je l'ai trouvé une réponse.

Ce que je veux est quelque chose comme l'application iOS Twitter. Si vous cliquez sur la loupe dans l'onglet Timelines, apparaît de UISearchBar avec le bouton Annuler activé, la projection du clavier et l'écran de recherches récentes. Faites défiler les recherches récentes écran et il cache le clavier, mais il maintient le bouton Annuler activé.

Ceci est mon code de travail:

UIView *searchBarSubview = self.searchBar.subviews[0];
NSArray *subviewCache = [searchBarSubview valueForKeyPath:@"subviewCache"];
if ([subviewCache[2] respondsToSelector:@selector(setEnabled:)]) {
    [subviewCache[2] setValue:@YES forKeyPath:@"enabled"];
}

Je suis arrivé à cette solution en mettant un point d'arrêt à la scrollViewWillBeginDragging: de mon point de vue de la table. Je regardais dans mon UISearchBar et montrai ses sous-vues. Il a toujours un seul, qui est de type UIView (ma searchBarSubview variable).

entrer image description ici

Alors que UIView est titulaire d'un NSArray appelé subviewCache et je remarque que le dernier élément, qui est le troisième, est de type UINavigationButton, pas dans l'API publique. Je suis donc parti d'utiliser une clé de codage de la valeur à la place. J'ai vérifié si le UINavigationButton répond à setEnabled:, et heureusement, il le fait. Je me suis donc la propriété à @YES. Avère que ce UINavigationButton le bouton Annuler.

Ceci est lié à briser si Apple décide de changer la mise en œuvre des entrailles d'un UISearchBar, mais ce que l'enfer. Il fonctionne pour l'instant.

ma réponse ici , placez dans votre délégué SearchBar:

- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar
{   
    dispatch_async(dispatch_get_main_queue(), ^{
        __block __weak void (^weakEnsureCancelButtonRemainsEnabled)(UIView *);
        void (^ensureCancelButtonRemainsEnabled)(UIView *);
        weakEnsureCancelButtonRemainsEnabled = ensureCancelButtonRemainsEnabled = ^(UIView *view) {
            for (UIView *subview in view.subviews) {
                if ([subview isKindOfClass:[UIControl class]]) {
                    [(UIControl *)subview setEnabled:YES];
                }
                weakEnsureCancelButtonRemainsEnabled(subview);
            }
        };

        ensureCancelButtonRemainsEnabled(searchBar);
    });
}

Pour MonoTouch ou iOS Xamarin j'ai la solution C # suivant travail pour iOS 7 et iOS 8:

foreach(UIView view in searchBar.Subviews)
{
    foreach(var subview in view.Subviews)
    {
        //Console.WriteLine(subview.GetType());
        if(subview.GetType() == typeof(UIButton))
        {
            if(subview.RespondsToSelector(new Selector("setEnabled:")))
            {
                UIButton cancelButton = (UIButton)subview;
                cancelButton.Enabled = true;
                Console.WriteLine("enabledCancelButton");
                return;
            }
        }
    }
}

Cette réponse est basée sur la solution de David Douglas.

Une réponse plus complète:

  • depuis iOS 7, il y a un niveau supplémentaire de sous-vues sous la barre de recherche
  • un bon endroit pour activer le bouton d'annulation est searchBarTextDidEndEditing

.

extension MyController: UISearchBarDelegate {
  public func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
    DispatchQueue.main.async {
    // you need that since the disabling will
    // happen after searchBarTextDidEndEditing is called
      searchBar.subviews.forEach({ view in
        view.subviews.forEach({ subview in
          // ios 7+
          if let cancelButton = subview as? UIButton {
            cancelButton.isEnabled = true
            cancelButton.isUserInteractionEnabled = true
            return
          }
        })
        // ios 7-
        if let cancelButton = subview as? UIButton {
          cancelButton.isEnabled = true
          cancelButton.isUserInteractionEnabled = true
          return
        }
      })
    }
  }
}

Voici une solution rapide de 3 qui utilise des extensions pour obtenir le bouton Annuler facilement:

extension UISearchBar {
    var cancelButton: UIButton? {
        for subView1 in subviews {
            for subView2 in subView1.subviews {
                if let cancelButton = subView2 as? UIButton {
                    return cancelButton
                }
            }
        }
        return nil
    }
}

Maintenant, pour l'utilisation:

class MyTableViewController : UITableViewController, UISearchBarDelegate {

    var searchBar = UISearchBar()

    func viewDidLoad() {
        super.viewDidLoad()
        searchBar.delegate = self
        tableView.tableHeaderView = searchBar
    }

    func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
        DispatchQueue.main.async {
            if let cancelButton = searchBar.cancelButton {
                cancelButton.isEnabled = true
                cancelButton.isUserInteractionEnabled = true
            }
        }
    }
}
scroll top