Frage

Ich habe eine UISearchBar, die für eine Tabellenansicht als Live-Filter wirkt. Wenn die Tastatur über endEditing des Feldes verwiesen :, die Abfragetext und die graue Kreis „clear“ -Taste bleiben. Von hier aus, wenn ich die graue Schaltfläche „Löschen“ tippen erscheint die Tastatur als der Text gelöscht wird.

Wie verhindere ich das? Wenn die Tastatur nicht geöffnet ist mag ich, dass, um den Text zu löschen, ohne die Tastatur wieder zu öffnen.

Es gibt ein Protokoll Methode, die aufgerufen wird, wenn ich die Löschtaste tippen. Aber zu senden UISearchBar eine ResignFirstResponder Nachricht hat keine Auswirkungen auf die Tastatur.

War es hilfreich?

Lösung

Dies ist eine alte Frage, und ich kam gerade über das gleiche Problem und schaffte es die folgende Art und Weise zu lösen:

Wenn die searchBar:textDidChange: Methode des UISearchBarDelegate wegen der Benutzer aufgerufen wird, die ‚klar‘ Taste tippen, hat die SearchBar nicht das erste Responder noch werden, so dass wir, um das auszunutzen zu erkennen, wenn der Benutzer in der Tat sollte die Suche löschen und nicht den Fokus auf die SearchBar zu bringen und / oder etwas anderes tun.

Spur davon zu halten, brauchen wir eine BOOL Ivar in unseren Viewcontroller zu erklären, dass auch die SearchBar Delegierten sind (sie es shouldBeginEditing nennen) und setzen Sie sie mit einem Anfangswert von YES (unsere Viewcontroller Klasse angenommen heißt SearchViewController):

@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;
    }
}
...
@end

Später, in der UISearchBarDelegate, setzen wir die searchBar:textDidChange: und searchBarShouldBeginEditing: Methoden:

- (void)searchBar:(UISearchBar *)bar textDidChange:(NSString *)searchText {
    NSLog(@"searchBar:textDidChange: isFirstResponder: %i", [self.searchBar isFirstResponder]);
    if(![searchBar isFirstResponder]) {
        // user tapped the 'clear' button
        shouldBeginEditing = NO;
        // do whatever I want to happen when the user clears the search...
    }
}


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

Im Grunde genommen, das ist es.

Best

Andere Tipps

Ich habe festgestellt, dass ResignFirstResponder funktioniert nicht, wenn textDidChange von einem Kontakt zu der „Löschtaste“ genannt wird. Allerdings performSelection: withObject: afterDelay: Verwendung scheint eine wirksame Abhilfe zu sein:

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
    if ([searchText length] == 0) {
        [self performSelector:@selector(hideKeyboardWithSearchBar:) withObject:searchBar afterDelay:0];
    }
}

- (void)hideKeyboardWithSearchBar:(UISearchBar *)searchBar
{   
    [searchBar resignFirstResponder];   
}

fand ich eine ziemlich sichere Art und Weise zu wissen, ob die Löschtaste gedrückt wurde, und die Zeiten, zu ignorieren, wenn der Benutzer nur das letzte Zeichen des UISearchBar löschen. Hier ist sie:

- (BOOL)searchBar:(UISearchBar *)searchBar shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
    _isRemovingTextWithBackspace = ([searchBar.text stringByReplacingCharactersInRange:range withString:text].length == 0);

    return YES;
}

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
    if (searchText.length == 0 && !_isRemovingTextWithBackspace)
    {
        NSLog(@"Has clicked on clear !");
    }
}

Ganz einfach und unkompliziert, ist es nicht :)? Das einzige, was zu beachten ist, dass, wenn der Benutzer die Löschtaste klickt, wenn die UITextField UISearchBar Bearbeiten Sie zwei Pings haben, während Sie ein nur erhalten, wenn der Benutzer darauf klickt, wenn er nicht bearbeitet wird.


Edit: Ich kann es nicht testen, aber hier ist die schnelle Version, wie pro Rotum:

var isRemovingTextWithBackspace = false

func searchBar(searchBar: UISearchBar, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool
{
    self.isRemovingTextWithBackspace = (NSString(string: searchBar.text!).stringByReplacingCharactersInRange(range, withString: text).characters.count == 0)
    return true
}

func searchBar(searchBar: UISearchBar, textDidChange searchText: String)
{
    if searchText.characters.count == 0 && !isRemovingTextWithBackspace
    { 
        NSLog("Has clicked on clear !")
    }
}

@ Rotum von update (Swift2):

var isRemovingTextWithBackspace = false

func searchBar(searchBar: UISearchBar, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {
    self.isRemovingTextWithBackspace = (NSString(string: searchBar.text!).stringByReplacingCharactersInRange(range, withString: text).characters.count == 0)
    return true
}

func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
    if searchText.characters.count == 0 && !isRemovingTextWithBackspace {
        NSLog("Has clicked on clear!")
    }
}

habe ich eine Kombination von Antwort des @ Boliva und auch @ radiospiel zu einer anderen SO Frage beantworten :

@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

Beste Lösung aus meiner Erfahrung ist nur ein UIButton zu setzen (mit klarem Hintergrund und ohne Text) über dem System Löschtaste und als ein IBAction verbinden

Mit automatischem Layout sein gerade mehr als einfach

- (IBAction)searchCancelButtonPressed:(id)sender {

    [self.searchBar resignFirstResponder];
    self.searchBar.text = @"";

    // some of my stuff
    self.model.fastSearchText = nil;
    [self.model fetchData];
    [self reloadTableViewAnimated:NO];

}

Durch Betätigen der Schaltfläche „Löschen“ in eine UISearchBar die Tastatur automatisch öffnet, auch wenn Sie searchBar.resignFirstResponder() im textDidChange UISearchBarDelegate Methode aufrufen.

Um die Tastatur tatsächlich zu verbergen, wenn Sie auf das „x“ drücken Sie die UISearchBar zu löschen, verwenden Sie den folgenden Code ein. Auf diese Weise, auch wenn textDidChange aufgerufen wird, während etwas in der UISearchBar eingeben, nur die Tastatur ausblenden, wenn Sie in ihm den gesamten Text löschen, Wetter verwenden Sie die Schaltfläche Löschen oder Sie klicken auf das „x“:

extension ViewController: UISearchBarDelegate {
    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        if searchBar.text!.count == 0 {
            DispatchQueue.main.async {
                searchBar.resignFirstResponder()
            }
        } else {
            // Code to make a request here.
        }
    }
}

In Ihrer endEditing Methode, warum Sie nicht die UISearchBar löschen und da? Da das sein muss, wo man auch Ersthelfer zurücktreten, es macht Sinn.

Von den Suchleiste Delegaten Anrufe aufgefordert, einen Wechsel von einem alten Wert zu einem neuen zu akzeptieren - man konnte erkennen, dass der neue Wert war gleich Null, zusammen mit dem alten Wert ist nicht zu null, und ein Indikator dafür, dass die Benutzer hatte getippt nichts, da die Tastatur bis zuletzt - dann in diesem Fall zurücktreten Ersthelfer für die Suchleiste. Nicht sicher, ob die Tastatur vorübergehend obwohl angezeigt.

Ich habe eine sehr ähnliche Situation und versuche, dass ich selbst.

Das Berühren der Löschtaste führt searchText leer zu sein. Ein anderer Weg, dies zu erreichen, ist für leeren Text in - (void)searchBar:(UISearchBar *)bar textDidChange:(NSString *)searchText zu überprüfen:

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
    if([searchText length] == 0)
    {
        [self dismissSearch];
    }
    else
    {
        self.searchResultsTable.hidden = YES;
        [self handleSearchForString:searchText];
    }
}

- (void)dismissSearch
{
    [self.searchBar performSelector: @selector(resignFirstResponder)
                  withObject: nil
                  afterDelay: 0.1];

    self.searchResultsTable.hidden = YES;
}

Für die von Ihnen die UISearchController in mit iOS 8 und oben, Sie wollen einfach die UISearchController Unterklasse. Für Vollständigkeit, können Sie auch die Abbrechen , um zu verbergen, wie ich, da von der UISearchBar den Text Clearing eine auf der Suche ist verworfen. Ich habe diesen Code unten hinzugefügt, wenn Sie es verwenden möchten.

Der Vorteil davon ist, dass Sie in der Lage sein werden dies für jede Klasse und jede Ansicht zu verwenden, anstatt eine Unterklasse von UIViewController erfordern. Ich werde sogar zählen, wie ich meine UISearchController am unteren Rand dieser Lösung initialisieren.

FJSearchBar

Diese Klasse muss nur außer Kraft gesetzt werden, wenn Sie die Löschtaste verstecken wollen wie ich. searchController.searchBar.showsCancelButton = NO Kennzeichnung scheint nicht in Arbeit iOS 8 . Ich habe nicht getestet iOS 9 .

FJSearchBar.h

leer, aber der Vollständigkeit halber hier gestellt.

@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

Hier ist, wo Sie die wirklichen Änderungen vornehmen möchten. Ich spaltete die UISearchBarDelegate in eine eigene Kategorie, denn meiner Meinung nach, die Kategorien der Klassen sauberer und leichter zu pflegen. Wenn Sie die Delegierten in der Hauptklasse Schnittstelle / Implementierung halten wollen, sind Sie mehr als willkommen, dies zu tun.

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

Einige Teile zu beachten:

  1. Ich habe anstelle von Eigenschaften der Suchleiste und die BOOL als private Variablen setzen, weil
    • Sie sind leichter als private Eigenschaften.
    • Sie brauchen nicht von der Außenwelt gesehen oder geändert werden.
  2. Wir prüfen, ob die searchBar der Ersthelfer ist. Wenn es nicht ist, dann tatsächlich deaktivieren wir die Suchsteuerung, da der Text leer ist und wir nicht mehr suchen. Wenn Sie wirklich Sie sicher sein wollen, können Sie auch, dass searchText.length == 0 gewährleisten.
  3. searchBar:textDidChange: vor searchBarShouldBeginEditing: aufgerufen, weshalb wir es in dieser Reihenfolge behandelt.
  4. aktualisiere ich die Suchergebnisse der Text ändert jedes Mal, aber Sie können die [self.searchResultsUpdater updateSearchResultsForSearchController:self]; searchBarSearchButtonClicked: wenn Sie nur die nach dem Benutzer durchgeführten Suche wollen verschieben möchten drückt die Suchen Taste.

Eine Swift-Version von @boliva ‚s Antwort.

class MySearchContentController: UISearchBarDelegate {

    private var searchBarShouldBeginEditing = true

    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        searchBarShouldBeginEditing = searchBar.isFirstResponder
    }

    func searchBarShouldBeginEditing(_ searchBar: UISearchBar) -> Bool {
        defer {
            searchBarShouldBeginEditing = true
        }
        return searchBarShouldBeginEditing
    }
}

Ich habe jetzt in diesen mehrmals ausgeführt werden. Ich schätze die Antworten, die Menschen gegeben haben.

Schließlich würde Ich mag Apple sehen uns nur erlauben (Entwickler) zu erkennen, wenn die Löschtaste gedrückt wurde.

Es ist offensichtlich, dass das Drücken es, weil jeder Text in dem Suchfeld gelöscht wird erkannt wird.

Ich vermute, dass es ist einfach nicht sehr hoch im Augenblick auf ihrer Prioritätenliste ... Aber ich mag wirklich jemand bei Apple würde UISearchBar eine wenig Liebe geben!

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top