UISearchBar Cancel Button

2019-04-05 20:02发布

问题:

Using a UISearchBar with showCancelButton=YES on iOS 5. Would like the cancel button to stay enabled when the keyboard drops down. Using the following code seems not to work:

    for (id subView in self.searchControl.subviews)
    {
        if ([subView isKindOfClass:[UIButton class]])
        {
            UIButton *cancelButton = (UIButton *)subView;
            [cancelButton setEnabled:YES];
            break;
        }         
    }

The subView is actually a UINavigationButton which appears not to be subclassed off of UIButton. What am I missing here??????? Also cannot find any info on the UINavigationButton class in the Apple docs.

回答1:

Set your searchbar delegate and than put this code.

- (void) searchBarSearchButtonClicked:(UISearchBar*) theSearchBar
  {
     [theSearchBar resignFirstResponder];
     [theSearchBar setShowsCancelButton:NO animated:YES];
  }
 - (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar
  {
     [searchBar setShowsCancelButton:YES animated:YES];
  }
  - (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
  {
     [searchBar resignFirstResponder];
     [searchBar setShowsCancelButton:NO animated:YES];
  }

Swift 3.0

func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
     searchBar .resignFirstResponder()
     searchBar.setShowsCancelButton(false, animated: true)
}
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
     searchBar.setShowsCancelButton(true, animated: true)
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
     searchBar.resignFirstResponder()
     searchBar.setShowsCancelButton(false, animated: true)
}


回答2:

Just to improve upon what Kurt Spindler said on his post. Though this might not be superior but it is more contained. I use dispatch to do the same thing.

-(void)searchBarTextDidEndEditing:(UISearchBar *)searchBar{
    for (UIView *subview in searchBar.subviews)
    {
        if ([subview isKindOfClass:[UIButton class]])
        {
            int64_t delayInSeconds = .001;
            dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
            dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
                UIButton * cancelButton = (UIButton *)subview;
                [cancelButton setEnabled:YES];
            });
            break;
        }
    }
}

This should work for everyone who needs help keep cancel enabled. Make sure that you hide it later either with the cancel or Search clicked.

- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar{
    [searchBar resignFirstResponder];
    [searchBar setShowsCancelButton:NO animated:YES];
}


回答3:

I placed a custom cancel button over the search bar cancel button.



回答4:

I had to solve the same problem in my application. Try doing your above code after a fractional delay, e.g.

[self performSelector:@selector(delayedEnable:) withObject:cancelButton afterDelay:0.001];

- (void)delayedEnable:(UIButton*)button {
    button.enabled = YES;
}

It's ugly, but that's what it took to work for me. Alternatively, if you actually use a UISearchDisplayController to display the results, it should also fix the cancel button behavior for you (I think - I've delved into this issue less).



回答5:

I know this one is old, but I was able to solve it and I couldn't find anything else on SO that solved it for me, so here's what worked (in Swift 3):

Enable the cancel button when the keyboard hides. Add this to viewDidLoad():

NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardNotification(notification:)), name: NSNotification.Name.UIKeyboardDidHide, object: nil)

in the keyboardNotification(notification:) method, react to the keyboardDidHide notification:

func keyboardNotification(notification: NSNotification) {
    if notification.name == Notification.Name.UIKeyboardDidHide {
        self.enableSearchCancelButton()
    }
}

The enableSearchCancelButton is taken from what others have answered here.

func enableSearchCancelButton() {
    //enable the cancel button
    for view1 in searchBar.subviews {
        for view2 in view1.subviews {
            if let button = view2 as? UIButton {
                button.isEnabled = true
                button.isUserInteractionEnabled = true
            }
        }
    }
}

Finally, don't forget to remove the view controller as an observer:

deinit {
    NotificationCenter.default.removeObserver(self)
}


回答6:

Swift 4:

if let btnCancel = searchBar.value(forKey: "cancelButton") as? UIButton {
    btnCancel.isEnabled = true
}


标签: uisearchbar