UISearchBar Cancel Button
Solution 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)
}
Solution 2
Swift 5:, Swift 4:
if let btnCancel = searchBar.value(forKey: "cancelButton") as? UIButton {
btnCancel.isEnabled = true
}
Solution 3
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];
}
Solution 4
I placed a custom cancel button over the search bar cancel button.
Solution 5
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).
Jim B
Updated on January 24, 2022Comments
-
Jim B over 2 years
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.
-
Imre Kelényi over 11 yearsIf you want to perform something asynchronously, just use dispatch_async. You don't need dispatch_after with an "almost instant delay value". E.g. in this case
dispatch_async(dispatch_get_main_queue(), ^(void){...});
works perfectly fine. -
Byte over 11 yearsI believe the 0.001 was necessary based on the answer by Kurt. If that is not the case, then your approach would be perfectly acceptable.
-
NSPratik over 7 yearsThis is working like a magic..@Kurt Can you tell me from where you got this? Amazing..upvoted