Custom UISearchBar with UISearchController

纵然是瞬间 提交于 2019-11-27 02:49:23

问题


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:


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



回答2:


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




回答3:


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.




回答4:


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.



来源:https://stackoverflow.com/questions/25904213/custom-uisearchbar-with-uisearchcontroller

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!