UISearchBar deshabilitar la desactivación automática de botón cancelar

He implementado un UISearchBar en una vista de tabla y casi todo es trabajo, excepto una pequeña cosa: Cuando entro en el texto y, a continuación, pulse el botón de búsqueda en el teclado, el teclado desaparece, los resultados de la búsqueda son los únicos elementos que se muestran en la tabla, el texto permanece en el UISearchBar, pero el botón cancelar queda desactivada.

He estado tratando de conseguir mi lista tan cerca de la funcionalidad de la Apple app de contactos y cuando usted presiona el botón búsqueda en la aplicación, no deshabilitar el botón cancelar.

Cuando me miré en el UISearchBar archivo de encabezado, me di cuenta de una bandera para autoDisableCancelButton bajo el _searchBarFlags struct pero es privado.

Hay algo que me falta cuando me la instalación de la UISearchBar?

InformationsquelleAutor rplankenhorn | 2010-12-03

10 Kommentare

  1. 51

    He encontrado una solución. Usted puede usar esto para bucle para recorrer las subvistas de la barra de búsqueda y se habilita cuando la búsqueda se pulsa el botón en el teclado.

    for (UIView *possibleButton in searchBar.subviews)
    {
        if ([possibleButton isKindOfClass:[UIButton class]])
        {
            UIButton *cancelButton = (UIButton*)possibleButton;
            cancelButton.enabled = YES;
            break;
        }
    }
    • Esto no me funciona en iOS 6, ya que el botón sólo está presente una UINavigationButton que parece ser una clase privada.
    • ¿Has probado la configuración de la showsCancelButton propiedad en UISearchBar?
    • UINavigationButton es subclase si UIButton, por lo que este código funciona, y no hay ninguna clase privada de uso. github.com/kennytm/iphone-private-frameworks/blob/master/UIKit/…
    • Uno sólo tiene que utilizar en el momento adecuado, que es después de la barra de búsqueda de la pérdida de enfoque (resignFirstResponder).
    • A mí me funciona! Hice ((UIButton*)possibleButton).enabled = YES; como encontrar el uso de cancelButton demasiado.
  2. 15

    Tuve que forzarlo un poco para conseguir que el trabajo para mí en iOS7

    - (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;
                }
            }
        }
    }
    • Usted realmente debe acabo de volver de la instrucción interna si en lugar de romper. Que la sentencia break es sólo va a salir del interior del bucle for y seguirá lazo sobre la barra de búsquedas.subvistas incluso después de encontrar el botón de cancelar.
    • Buen punto, he actualizado mi respuesta.
  3. 5

    Hay dos manera de lograr esto fácilmente

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

    Usted debe ir con el segundo, no se cuelga de su aplicación si Apple va a cambiar en el fondo.

    Por CIERTO, he probado de iOS 4.0 8.2 y no hay cambios, también yo lo uso en mi Tienda de aplicaciones aprobadas sin ningún tipo de problemas.

    • Esto todavía funciona en iOS9.
    • Esto funciona, pero su aplicación puede ser rechazada como es el uso de un método privado. Ten cuidado.
    • no, esto no es realmente cuenta como privado, el uso de la api, y nunca he visto ningún rechaza a causa de esto.
  4. 3

    Esto es lo que hace que funcione en iOS 6 para mí:

    searchBar.showsCancelButton = YES;
    searchBar.showsScopeBar = YES;
    [searchBar sizeToFit];
    [searchBar setShowsCancelButton:YES animated:YES];
    
    • esto no resuelve el problema: el op quiere desactivar el auto-deshabilitar la función, es decir, no permitir que UISearchBar para desactivarlo.
  5. 3

    Aquí está mi solución, que funciona para todas las situaciones en todas las versiones de iOS.

    Es decir, otras soluciones no manejar cuando el teclado está desestimada porque el usuario arrastra un desplazamiento de la vista.

    - (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];
    
    • Buen código, gracias!
  6. 2

    Ninguna de las respuestas trabajado para mí en absoluto. Estoy de orientación de iOS 7. Pero he encontrado una respuesta.

    Lo que estoy tratando es algo así como la cuenta de Twitter de la aplicación de iOS. Si haces clic en la lupa que aparece en el cronograma de la ficha, el UISearchBar aparece con el botón Cancelar activado, el teclado muestra, y la búsquedas recientes de la pantalla. Desplazarse por la búsquedas recientes de la pantalla y se oculta el teclado, pero que mantiene el botón Cancelar activado.

    Este es mi código de trabajo:

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

    Llegué a esta solución por establecer un punto de interrupción en mi mesa de la vista scrollViewWillBeginDragging:. Miré a mi UISearchBar y desveló su subvistas. Siempre acaba uno, que es de tipo UIView (mi variable searchBarSubview).

    UISearchBar deshabilitar la desactivación automática de botón cancelar

    Entonces, que UIView tiene un NSArray llamado subviewCache y me di cuenta de que el último elemento, que es la tercera, es de tipo UINavigationButton, no en la API pública. Así que me puse a usar la llave-valor de codificación en su lugar. He comprobado si el UINavigationButton responde a setEnabled:, y por suerte, no. Así que me puse a la propiedad a @YES. Resulta que UINavigationButton es el botón Cancelar.

    Este está obligado a romper si Apple decide cambiar la implementación de un UISearchBar‘s de las vísceras, pero ¿qué demonios. Por ahora funciona.

  7. 2

    Como por mi respuesta aquí, lugar este en su barra de búsquedas delegado:

    - (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);
        });
    }
    
  8. 1

    Para Monotouch o Xamarin iOS tengo el siguiente C# solución de trabajo para iOS 7 y 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;
                }
            }
        }
    }
    

    Esta respuesta está basada en David Douglas solución.

  9. 1

    Una respuesta más completa:

    • desde iOS 7, hay un nivel adicional de subvistas debajo de la barra de búsquedas
    • un buen lugar para habilitar el botón cancelar es en 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
            }
          })
        }
      }
    }
    
  10. 1

    Aquí un Swift 3 solución que hace uso de extensiones para obtener el botón cancelar fácilmente:

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

    Ahora para el uso:

    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
                }
            }
        }
    }
    
    • Una solución más limpia que he visto. Gracias.

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea