The documentation for UISearchController
says that you can override - searchBar
to provide a custom subclass of UISearchBar
for the controller to use. The custom search bar does get used, and its own delegate methods are called correctly, but the UISearchResultsUpdating
method no longer gets called when the search bar changes. Do I need to do a lot of wiring things up manually, or is there something I'm missing to get the controller to behave like it does with a natively supplied search bar?

- 1,670
- 3
- 15
- 30
-
Nothing in there is using a subclassed UISearchController that I can see – Farski Sep 18 '14 at 11:28
-
Have there been any updates on this issue? I'm struggling with the same. I used custom `UISearchBar` and `UISearchController` to avoid the Cancel button showing up. Now, `UISearchResultsUpdating` doesn't get called on search text changes, and therefore the results table fails to show up at all. – artooras Jul 06 '15 at 08:25
-
searchController.searchBar.showsCancelButton = NO – malhal Oct 26 '18 at 08:43
4 Answers
Override the SearchBar getter in your custom UISearchController class, it have to return your custom SearchBar and it have to be already initialized, then you setup its properties only after the UISearchController init, this way all the UISearchController functionality are retained:
public class DSearchController: UISearchController {
private var customSearchBar = DSearchBar()
override public var searchBar: UISearchBar {
get {
return customSearchBar
}
}
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
public init(searchResultsController: UIViewController?,
searchResultsUpdater: UISearchResultsUpdating?,
delegate: UISearchControllerDelegate?,
dimsBackgroundDuringPresentation: Bool,
hidesNavigationBarDuringPresentation: Bool,
searchBarDelegate: UISearchBarDelegate?,
searchBarFrame: CGRect?,
searchBarStyle: UISearchBarStyle,
searchBarPlaceHolder: String,
searchBarFont: UIFont?,
searchBarTextColor: UIColor?,
searchBarBarTintColor: UIColor?, // Bar background
searchBarTintColor: UIColor) { // Cursor and bottom line
super.init(searchResultsController: searchResultsController)
self.searchResultsUpdater = searchResultsUpdater
self.delegate = delegate
self.dimsBackgroundDuringPresentation = dimsBackgroundDuringPresentation
self.hidesNavigationBarDuringPresentation = hidesNavigationBarDuringPresentation
customSearchBar.setUp(searchBarDelegate,
frame: searchBarFrame,
barStyle: searchBarStyle,
placeholder: searchBarPlaceHolder,
font: searchBarFont,
textColor: searchBarTextColor,
barTintColor: searchBarBarTintColor,
tintColor: searchBarTintColor)
}
}
And this is my custom searchBar:
public class DSearchBar: UISearchBar {
var preferredFont: UIFont?
var preferredTextColor: UIColor?
init(){
super.init(frame: CGRect.zero)
}
func setUp(delegate: UISearchBarDelegate?,
frame: CGRect?,
barStyle: UISearchBarStyle,
placeholder: String,
font: UIFont?,
textColor: UIColor?,
barTintColor: UIColor?,
tintColor: UIColor?) {
self.delegate = delegate
self.frame = frame ?? self.frame
self.searchBarStyle = searchBarStyle
self.placeholder = placeholder
self.preferredFont = font
self.preferredTextColor = textColor
self.barTintColor = barTintColor ?? self.barTintColor
self.tintColor = tintColor ?? self.tintColor
self.bottomLineColor = tintColor ?? UIColor.clearColor()
sizeToFit()
// translucent = false
// showsBookmarkButton = false
// showsCancelButton = true
// setShowsCancelButton(false, animated: false)
// customSearchBar.backgroundImage = UIImage()
}
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
let bottomLine = CAShapeLayer()
var bottomLineColor = UIColor.clearColor()
override public func layoutSubviews() {
super.layoutSubviews()
for view in subviews {
if let searchField = view as? UITextField { setSearchFieldAppearance(searchField); break }
else {
for sView in view.subviews {
if let searchField = sView as? UITextField { setSearchFieldAppearance(searchField); break }
}
}
}
bottomLine.path = UIBezierPath(rect: CGRectMake(0.0, frame.size.height - 1, frame.size.width, 1.0)).CGPath
bottomLine.fillColor = bottomLineColor.CGColor
layer.addSublayer(bottomLine)
}
func setSearchFieldAppearance(searchField: UITextField) {
searchField.frame = CGRectMake(5.0, 5.0, frame.size.width - 10.0, frame.size.height - 10.0)
searchField.font = preferredFont ?? searchField.font
searchField.textColor = preferredTextColor ?? searchField.textColor
//searchField.backgroundColor = UIColor.clearColor()
//backgroundImage = UIImage()
}
}
Init example:
searchController = DSearchController(searchResultsController: ls,
searchResultsUpdater: self,
delegate: self,
dimsBackgroundDuringPresentation: true,
hidesNavigationBarDuringPresentation: true,
searchBarDelegate: ls,
searchBarFrame: CGRectMake(0.0, 0.0, SCREEN_WIDTH, 44.0),
searchBarStyle: .Minimal,
searchBarPlaceHolder: NSLocalizedString("Search a location...", comment: ""),
searchBarFont: nil,
searchBarTextColor: nil,
searchBarBarTintColor: UIColor.whiteColor(),
searchBarTintColor: iconsColor)
searchController.searchBar.keyboardAppearance = .Dark
definesPresentationContext = true
tableView.tableHeaderView = searchController.searchBar

- 1,215
- 12
- 12
This is a known bug. Unfortunately, there is no workaround that does not involve private API.

- 1,650
- 14
- 19
-
Can you elaborate on this? I can't find any mention of this issue as a known bug. – pbuchheit Oct 10 '14 at 15:43
-
@Alex UISearchController is available only in iOS 8 and on. The compiler won't recognize the class in iOS 7 and below. Stick with UISearchDisplayController until you are only supporting iOS 8 and above. – Brian Sachetta Feb 05 '15 at 21:36
-
@MyztikJenz, do you know if there have been any changes regarding this bug? My problem is that the search results table fails to show up altogether because `UISearchResultsUpdating` doesn't get called on search text changes with a custom `UISearchBar`. – artooras Jul 06 '15 at 08:27
When you subclass UISearchController you can customise UISearchBar in getter (setter doesn't exist).
Example - in subclass implementation:
-(UISearchBar*)searchBar{
UISearchBar *baseSearchBar = [super searchBar];
if (baseSearchBar.showsScopeBar) {
baseSearchBar.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 88);
}else{
baseSearchBar.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 44);
}
return baseSearchBar;
}
Hope this helps someone.

- 335
- 4
- 5
I think it's supposed to behave like that.
This is from UISearchController.h
// You are free to become the search bar's delegate to monitor for text changes and button presses.
@property (nonatomic, retain, readonly) UISearchBar *searchBar;
All that delegate method (updateSearchResultsForSearchController:) does is return your search controller so you can access its search bar.
You can just do that through your custom search bar delegate methods.

- 1,297
- 11
- 17