UISearchController in a UIViewController

前端 未结 4 1922
无人共我
无人共我 2020-12-28 10:13

I\'m looking to create similar functionality to Apple\'s maps application in Swift. Is there anyway to integrate a UISearchController in to a regular view (i.e.: not a UITab

相关标签:
4条回答
  • 2020-12-28 10:20

    I added a Search Bar and Search Display Controller in my View Controller in the storyboard. The view controller contains only the search bar and search display controller and does not have it's own TableView. When you add the search bar in your view controller, it sets your view controller as it's delegate automatically.

    Now the Search Bar and Search Display Controller has a table view of itself which it uses to display the search results when you click inside the box and start typing. This table view expects your view controller to provide the implementations of the numberOfRowsInSection and cellForRowAtIndexPath functions for it to display the data properly.

    When you run your project without these and tap inside the search bar, you will get the following error:-

    tableView:numberOfRowsInSection:]: unrecognized selector sent to instance 0x7fbf63449660 *** Terminating app due to uncaught exception 'NSInvalidArgumentException'

    If you see, the error is at the numberOfRowsInSection method.

    Change your view controller definition from

    class ViewController: UIViewController
    

    to

    class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource
    

    and implement the required methods which are:-

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        return UITableViewCell()
    }
    
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 0
    }
    

    I have just added default return values in the above methods.

    Now if you filter out your data source in your searchviewdelegate methods and set up your number of rows and cell info in the above two methods properly, it should work.

    Hope this helps!

    0 讨论(0)
  • 2020-12-28 10:34

    Trying to figure out UISearchController myself. Setting it to the titleView is convenient, but on one of my pages, I had to put the searchBar near the top of the UIViewController:

    // Add a normal View into the Storyboard.
    // Set constraints:
    // - height: 44
    // - leading and trailing so that it spans the width of the page
    // - vertical position can be anywhere based on your requirements, like near the top
    @IBOutlet weak var searchContainerView: UIView!
    
    var searchResultsController = UISearchController()
    
    override func viewDidLoad() {
        // TODO: set the searchResultsController to something
        let controller = UISearchController(searchResultsController: nil)
        // have the search bar span the width of the screen
        controller.searchBar.sizeToFit()
        // add search bar to empty View
        searchContainerView.addSubview(controller.searchBar)
        searchResultsController = controller
    }
    

    UPDATE:

    After implementing UISearchController in a project or two, I found myself gravitating toward @adauguet's approach of embedding the search bar into the Navigation Bar.

    Here's the code in Swift. One difference though is that it doesn't set the searchBar delegate, since searchResultsUpdater already listens for text changes.

    override func viewDidLoad() {
        super.viewDidLoad()
    //        locationManager.delegate = self
    //        locationManager.desiredAccuracy = kCLLocationAccuracyBest
    //        locationManager.requestWhenInUseAuthorization()
    //        locationManager.requestLocation()
        let locationSearchTable = storyboard!.instantiateViewControllerWithIdentifier("LocationSearchTable") as! LocationSearchTable
        resultSearchController = UISearchController(searchResultsController: locationSearchTable)
        resultSearchController?.searchResultsUpdater = locationSearchTable
        let searchBar = resultSearchController!.searchBar
        searchBar.sizeToFit()
        searchBar.placeholder = "Search for places"
        navigationItem.titleView = resultSearchController?.searchBar
        resultSearchController?.hidesNavigationBarDuringPresentation = false
        resultSearchController?.dimsBackgroundDuringPresentation = true
        definesPresentationContext = true
    }
    

    Also, I wrote a blog post that creates a project from scratch that uses UISearchController to display map search results. It also does other things that you might want in a map project, like get the user location, drop pins, parse placemarks into a one-line address, and create callout buttons that take you to Apple Maps for driving directions.

    http://www.thorntech.com/2016/01/how-to-search-for-location-using-apples-mapkit/

    The blog post is quite long, so here's the associated git repo if you just want to skip to the code:

    https://github.com/ThornTechPublic/MapKitTutorial

    0 讨论(0)
  • 2020-12-28 10:35

    If you want to use UISearchController with a non UITableView, here is how I did it.

    Since the UISearchController is not (yet!) supported by IB, you do not need to add anything in it, like a UISearchBar.

    @interface UIViewControllerSubclass () <UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate, UISearchControllerDelegate, UISearchResultsUpdating>
    
    @property (strong, nonatomic) UISearchController *searchController;
    
    @end
    
    @implementation UIViewControllerSubclass
    
    - (void)viewDidLoad
    {        
        [super viewDidLoad];
        // Do any custom init from here...
    
        // Create a UITableViewController to present search results since the actual view controller is not a subclass of UITableViewController in this case
        UITableViewController *searchResultsController = [[UITableViewController alloc] init];
    
        // Init UISearchController with the search results controller
        self.searchController = [[UISearchController alloc] initWithSearchResultsController:searchResultsController];
    
        // Link the search controller
        self.searchController.searchResultsUpdater = self;
    
        // This is obviously needed because the search bar will be contained in the navigation bar
        self.searchController.hidesNavigationBarDuringPresentation = NO;
    
        // Required (?) to set place a search bar in a navigation bar
        self.searchController.searchBar.searchBarStyle = UISearchBarStyleMinimal;
    
        // This is where you set the search bar in the navigation bar, instead of using table view's header ...
        self.navigationItem.titleView = self.searchController.searchBar;
    
        // To ensure search results controller is presented in the current view controller
        self.definesPresentationContext = YES;
    
        // Setting delegates and other stuff
        searchResultsController.tableView.dataSource = self;
        searchResultsController.tableView.delegate = self;
        self.searchController.delegate = self;
        self.searchController.dimsBackgroundDuringPresentation = NO;
        self.searchController.searchBar.delegate = self;        
    }
    
    @end
    

    I hope it is enough to work :-)

    Then of course you need at least to implement UITableViewDelegate, UITableViewDataSource, UISearchResultsUpdater methods.

    Enjoy!

    0 讨论(0)
  • 2020-12-28 10:36

    I had some trouble converting from SearchDisplayController in UIViewController to SearchController in ViewController because SearchController implementation isn't so intuitive. But you can just add in searcher from SearchController itself into any view. You cannot set constraint though because the search bar would move up when you focus/select it (if you know how to set the constraint to seachController.searchbar after adding it to any view, LET ME KNOW!). Below I am sharing a checklist that I found very important/valuable when implementing SearchController in ViewController.

    //you can just add searcher to any view. It would automatically move up to show the tableView like magic. But for this reason, you cannot set constraint to the search bar to the placeholder view that you are adding it to.

    [self.searchBarPlaceHolderView addSubview:self.searchController.searchBar];
    

    //you need this to prevent search bar to drop down when you focus/select it. You would want to set this to NO if you are adding searchBar to the navigation bar's titleview.

    self.searchController.hidesNavigationBarDuringPresentation = YES;
    

    //make sure you set this in your viewController

    self.extendedLayoutIncludesOpaqueBars = true;
    self.definesPresentationContext = YES;
    

    // you also need to give the search controller a tableViewController that can be displayed. You can also do just self.searchResultsController = [[UITableView alloc] init] for a generic one.

    self.searchResultsController = (UITableViewController *)[ [UIStoryboard storyboardWithName:@"Main" bundle:nil] instantiateViewControllerWithIdentifier:@"searchResultsTableViewController"];
    
    self.searchResultsController.tableView.dataSource = self;
    self.searchResultsController.tableView.delegate = self;
    self.searchResultsController.definesPresentationContext = NO;
    self.searchController = [[UISearchController alloc] initWithSearchResultsController:self.searchResultsController];
    
    0 讨论(0)
提交回复
热议问题