UISearchController searchBar showsCancelButton not

2020-06-08 13:38发布

问题:

I've added a UISearchController to my application and set it's searchBar to the titleView of my navigationItem.

This works but I am seeing the cancel button despite having set showsCancelButton to false.

    searchController = UISearchController(searchResultsController: searchResultsController)
    searchController.searchResultsUpdater = searchResultsUpdater


    // Configure the searchBar
    searchController.searchBar.placeholder = "Find Friends..."
    searchController.searchBar.sizeToFit()
    searchController.searchBar.showsCancelButton = false

    self.definesPresentationContext = true

    navigationItem.titleView = searchController.searchBar

回答1:

I agree, it seems like a bug. The problem is that the searchController keeps resetting the showsCancelButton property of the searchBar. I found a solution that involves:

  1. subclassing UISearchBar to ignore setShowsCancelButton.
  2. to make the searchController use that subclass, you have to subclass UISearchController.
  3. And then you find that the searchBar is not triggering the search controller's delegate methods, so you have to trigger them separately...

Convoluted, but it seems to do the trick. You can find the full answer here.



回答2:

This appears to be a bug in iOS. The same behavior I've described can be seen in the example project supplied by Apple

https://developer.apple.com/library/ios/samplecode/TableSearch_UISearchController/Introduction/Intro.html

The documentation states that the default for this is NO but this doesn't seem to be the case. Setting showsCancelButton to NO seems to have no effect.

I have filed a radar for this and am waiting to hear back.



回答3:

Easy solution in Swift3 - we need to make CustomSearchBar without cancel button and then override the corresponding property in new CustomSearchController:

class CustomSearchBar: UISearchBar {

override func setShowsCancelButton(_ showsCancelButton: Bool, animated: Bool) {
    super.setShowsCancelButton(false, animated: false)
}}


class CustomSearchController: UISearchController {

lazy var _searchBar: CustomSearchBar = {
    [unowned self] in
    let customSearchBar = CustomSearchBar(frame: CGRect.zero)
    return customSearchBar
    }()

override var searchBar: UISearchBar {
    get {
        return _searchBar
    }
}}

In MyViewController I initialize and configure searchController using this new custom subclass:

    var mySearchController: UISearchController = ({
    // Display search results in a separate view controller
    //        let storyBoard = UIStoryboard(name: "Main", bundle: Bundle.main)
    //        let alternateController = storyBoard.instantiateViewController(withIdentifier: "aTV") as! AlternateTableViewController
    //        let controller = UISearchController(searchResultsController: alternateController)
    let controller = CustomSearchController(searchResultsController: nil)
    controller.searchBar.placeholder = NSLocalizedString("Enter keyword (e.g. iceland)", comment: "")
    controller.hidesNavigationBarDuringPresentation = false
    controller.dimsBackgroundDuringPresentation = false
    controller.searchBar.searchBarStyle = .minimal
    controller.searchBar.sizeToFit()
    return controller
})()


回答4:

I had to correct by putting in a little hack...

Setting the alpha to 0.0 on viewDidLoad because he screen will flash.

Before you ask...willPresentSearchController will not work.

extension GDSearchTableViewController: UISearchControllerDelegate {
    func didPresentSearchController(searchController: UISearchController) {
        searchController.searchBar.setShowsCancelButton(false, animated: false)
        searchController.searchBar.becomeFirstResponder()
        UIView.animateWithDuration(0.1) { () -> Void in
            self.view.alpha = 1.0
            searchController.searchBar.alpha = 1.0
        }
    }
}


回答5:

We wanted the search bar to have no Cancel button initially, but have it appear when the user tapped in the search bar. Then we wanted the Cancel button to disappear if user tapped Cancel, or otherwise the search bar lost first responder.

What finally worked for me:

On create:

searchBar.showsCancelButton = NO;

We use a subclass of UISearchBar and override searchBarShouldBeginEditing thusly:

-(BOOL)searchBarShouldBeginEditing:(UISearchBar*)searchBar {
    self.showsCancelButton = YES;
    return YES;
}

We also override resignFirstReponder (in the UISearchBar subclass) thusly:

-(BOOL)resignFirstResponder
{
    self.showsCancelButton = NO;
    return [super resignFirstResponder];
}


回答6:

I would also add

searchController.hidesNavigationBarDuringPresentation = false
searchController.delegate = self
searchController.searchBar.delegate = self

See if assigning those delegates will help.



回答7:

I try to help you man but I'm not sure that I find the real problem.

According to Apple Documentation:

showsCancelButton

boolean property that indicating whether the cancel button is displayed

But for hide the cancel button maybe you should use:

setShowsCancelButton(_:animated:)

I hope that can be helpful.



回答8:

You can subclass UISearchBar and override method layoutSubviews

super.layoutSubviews()
self.showsCancelButton = false


回答9:

my solution was to set the attribute every time anew when I used the searchcontroller respectively its searchbar. I initialized the searchcontroller lazily without setting the attribute and then did

searchController.searchBar.showsCancelButton = false

every time before search began. You could do this in the UISearchControllerDelegate methods i.e...



回答10:

This worked for me (iOS 10):

- (void)viewWillAppear:(BOOL)animated {
      [super viewWillAppear:animated];
      self.searchController.searchBar.showsCancelButton = NO;
}


回答11:

It may be helpful to note that this has changed on iOS 13 and quote Apple's documentation on showsCancelButton, currently only available on UISearchBar.h and not on developer.apple.com

/* New behavior on iOS 13.
 If the search bar is owned by a UISearchController, then using the setter
 for this property (as well as -setShowsCancelButton:animated:) will implicitly
 set the UISearchController's automaticallyShowsCancelButton property to NO.
 */

automaticallyShowsCancelButton has been introduced on iOS 13.0 and should clarify what @pbasdf had already pointed out in his answer: that the buggy behavior is something intrinsic to UISearchController.



回答12:

What about setting it with [searchBar setShowsCancelButton:NO animated:NO];

https://developer.apple.com/library/ios/documentation/UIKit/Reference/UISearchBar_Class/#//apple_ref/occ/instm/UISearchBar/setShowsCancelButton:animated:



标签: ios xcode swift