Usuwanie klawiatury z paska UISearchBar po naciśnięciu przycisku X

Używam paska UISearchBar (ale nie SearchDisplayController, który jest zwykle używany w połączeniu) i chciałbym odrzucić klawiaturę po naciśnięciu przycisku 'X'.

Zastosowałem się do sugestii TomSwift ' a na temat bycia wywołanym, gdy 'X' jest na podsłuchu i to działa świetnie. Ale rezygnacja z pierwszego odpowiedzi z pola tekstowego, a także wywołanie w instancji UISearchBar, zarówno z resignFirstResponder, nie spowoduje odejścia klawiatury.

Czy jest sposób na pozbycie się klawiatury kiedy użytkownik nacisnął przycisk X?

Oto, co zrobiłem, aby uzyskać "jasne" powiadomienie:

- (void)viewDidLoad:
{
    for (UIView* v in searchBar.subviews)
    {
        if ( [v isKindOfClass: [UITextField class]] )
        {
            UITextField *tf = (UITextField *)v;
            tf.delegate = self;
            break;
        }
    }    
}

Następnie mam moją konfigurację klasy, aby zaimplementować zarówno UISearchBarDelegate, jak i UITextFieldDelegate.

Posiadanie klasy serve jako delegata textfield pozwala mi uzyskać to wywołanie:

- (BOOL)textFieldShouldClear:(UITextField *)textField
{
     [textField resignFirstResponder];
     [self.searchBar resignFirstResponder];
     return YES;
}
Próbowałem wszystkiego, co mogłem wymyślić. Ostatnią rzeczą, którą próbuję, jest znalezienie sposobu na wydanie "searchBarCancelButtonClicked", który uisearchdelegate wywoła na mojej klasie kontrolera, ale nie jestem pewien, jak mogłem to zrobić, ponieważ UISearchBar nie wydaje się mieć żadnych bezpośrednich metod do wywołania o tej nazwie.
Author: Community, 2010-11-16

13 answers

Update:

Cóż, to jest totalne włamanie, ale udało mi się to zrobić. Zasadniczo kod wywołuje obsługę przycisku Anuluj. Żeby się udało musiałem z opóźnieniem wywołać selektora i nie jestem pewien, dlaczego tak musiało być. Musiałem też napisać accessor dla przycisku Anuluj, tak jak ty dla pola tekstowego. / Align = "left" / Nie jestem pewien, czy zrobiłbym to sam w aplikacji.
// this in the context of the search bar
- (UIButton*) cancelButton
{
    for (UIView* v in self.subviews)
    {
        if ( [v isKindOfClass: [UIButton class]] )
            return (UIButton*)v;
    }

    return nil;
}

// this is the textField delegate callback
- (BOOL)textFieldShouldClear:(UITextField *)textField
{
    [textField resignFirstResponder];

    UIButton* cb = _searchBar.cancelButton;

    NSObject* target = [[cb allTargets] anyObject];

    NSArray* actions = [cb actionsForTarget: target forControlEvent:UIControlEventTouchUpInside];

    NSString* selectorName = [actions  objectAtIndex:0];

    SEL selector = NSSelectorFromString( selectorName );

    [target performSelector: selector withObject: cb afterDelay: 0.1];

    return YES;
}

Oryginalna odpowiedź:

Jak masz jasny przycisk "X", aby wyświetlić w pierwszej kolejności? W moim przypadku testowym nie widzę go wyświetlania...

Spróbuj zrobić resignFirstResponder na pasku wyszukiwania, a nie w polu tekstowym.

 2
Author: TomSwift,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-11-17 05:19:49

Toms odpowiedzi dał mi do myślenia. Jeśli pasek wyszukiwania nie jest jeszcze firstResponder, gdy użytkownik kliknie przycisk Wyczyść, możemy po prostu poczekać, aż będzie, a następnie mieć go recipfirstresponder; tzn. wzdłuż linii:

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
  [self performFilteringBySearchText: searchText]; // or whatever

  // The user clicked the [X] button or otherwise cleared the text.
  if([searchText length] == 0) {
    [searchBar performSelector: @selector(resignFirstResponder) 
                    withObject: nil 
                    afterDelay: 0.1];
  }
}
Działa jak czar i mniej hakerski niż IMHO Toma.
 70
Author: radiospiel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-31 18:20:51

To działa:

[searchBar performSelector:@selector(resignFirstResponder) withObject:nil afterDelay:0.1];
 6
Author: pickwick,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-20 21:07:35

Wersja Swift 2:

func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
        // The user clicked the [X] button or otherwise cleared the text.
        if (searchText.characters.count == 0) {
            searchBar.performSelector("resignFirstResponder", withObject: nil, afterDelay: 0.1)
        }
    }
 3
Author: powertoold,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-01 01:08:11

Aktualizacja dla SWIFT 3:

Załóżmy, że użytkownik wprowadził ciąg znaków w polu wyszukiwania i kliknie x poniższy kod działa, aby ukryć klawiaturę po naciśnięciu x

`

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) 
{
            if searchBar.text == nil || searchBar.text == ""
            {
                searchBar.perform(#selector(self.resignFirstResponder), with: nil, afterDelay: 0.1)
            }
 }

`

 3
Author: Ammad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-25 16:18:28

Możesz zrezygnować, klikając przycisk Anuluj jako.

- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar

{

    SearchBar.showsCancelButton =NO;

}


- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
{

    [SearchBar resignFirstResponder];


}
 2
Author: Sabby,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-11-16 04:33:57

Znalazłem to w poprzednim pytaniu:

Uisearchbar clearButton wymusza pojawienie się klawiatury

Powinno robić dokładnie to, co chcesz zrobić.

 1
Author: Tozar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:01

Staraj się unikać

- (BOOL)searchBarShouldEndEditing:(UISearchBar *)searchBar

Metoda w Twoim kodzie możemy rozwiązać ten

 1
Author: Ganesh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-22 11:30:31

Użyłem kombinacji odpowiedzi @ radiospiel, a także odpowiedzi, którą @ Tozar podlinkował do:

@interface SearchViewController : UIViewController <UISearchBarDelegate> {
    // all of our ivar declarations go here...
    BOOL shouldBeginEditing;
    ....
}

...
@end

@implementation SearchViewController
...
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
        ...
        shouldBeginEditing = YES;
    }
}
...

- (void) searchBar:(UISearchBar *)theSearchBar textDidChange:(NSString *)searchText {
    // TODO - dynamically update the search results here, if we choose to do that.

    if (![searchBar isFirstResponder]) {
        // The user clicked the [X] button while the keyboard was hidden
        shouldBeginEditing = NO;
    }
    else if ([searchText length] == 0) {
        // The user clicked the [X] button or otherwise cleared the text.
        [theSearchBar performSelector: @selector(resignFirstResponder)
                        withObject: nil
                        afterDelay: 0.1];
    }
}

- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)bar {
    // reset the shouldBeginEditing BOOL ivar to YES, but first take its value and use it to return it from the method call
    BOOL boolToReturn = shouldBeginEditing;
    shouldBeginEditing = YES;
    return boolToReturn;
}
@end
 1
Author: benvolioT,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:09:54

Czy zmiany interfejsu nie powinny być wprowadzane w głównym wątku zamiast performselector:WithObject:afterDelay:?

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
    if (searchText.length == 0) {
        [searchBar performSelectorOnMainThread:@selector(resignFirstResponder) withObject:nil waitUntilDone:NO];
    }
}
 1
Author: Luca Gobbo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-21 12:30:35

EDIT: w rzeczywistości poniższy fragment łamie delegata, który jest połączony z paskiem UISearchBar. Wystarczy podklasować UISearchBar i nadpisać metodę delegata UITextField.

===========================

Musiałem to zrobić, aby uzyskać dostęp do UITextView

for (UIButton* v in [self.searchBar.subviews[0] subviews])
{
    if ( [v isKindOfClass: [UITextField class]] )
    {
        UITextField *tf = (UITextField *)v;
        tf.delegate = self;
        break;
    }
}
 0
Author: Rich Fox,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-28 19:04:39

Kredyt dla Maxhs za oryginalną odpowiedź : Jest to wersja swift 2.2 : Pracuj jak urok dla mnie

if searchBar.text == "" {
                dispatch_async(dispatch_get_main_queue(), { 
                    self.searchBar.resignFirstResponder()
                })
            }
 0
Author: Alix,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-16 04:55:23

Kolejny punkt widzenia na jasny Przepływ tekstu(podobny do odpowiedzi @ TomSwift, ale dla mnie jaśniejszy i mniej skomplikowany). Ponadto, muszę ukryć przycisk Anuluj po wyjściu z paska wyszukiwania, zaimplementować live search (po każdym symbolu) i przykryć tabelę przed użytkownikiem zakończyć wyszukiwanie.

//self.searchHoverView can cover table view
//performSearchWithSearchBar: method for performing search

#pragma mark - UISearchBarDelegate

- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
    [searchBar setShowsCancelButton:YES animated:YES];
    self.searchHoverView.hidden = NO;
}

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
    if (searchText.length) {
        [self performSearchWithSearchBar:searchBar];
    } else {
        UIButton *button;
        for (UIView *subView in [searchBar subviews]) {
            for (UIView *view in [subView subviews]) {
                if ([view isKindOfClass:[UIButton class]]) {
                    button = (UIButton *)view;
                    break;
                }
            }
        }

        if (button) {
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                [button sendActionsForControlEvents:UIControlEventTouchUpInside];
            });
        }
    }
}

- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
    self.searchBar.text = nil;

    [self.searchBar setShowsCancelButton:NO animated:YES];
    [self.searchBar resignFirstResponder];

    self.searchHoverView.hidden = YES;
}
 0
Author: WINSergey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-28 11:51:22