Swift if Text Changes in Search Bar Search Again

Overview

Providing a way for users to search through a collection of items is a fairly mutual task in iOS projects. A standard interface for implementing search behaviors is the search bar.

There are a few common means to work with Search Confined:

  • Direct using a UISearchBar . This is the near bare bones fashion to use UISearchBars. This tin be extremely flexible if you lot want to blueprint and program your own search interface, however does not provide equally many built-in features as the other methods.

  • Using a UISearchDisplayController to help manage a search interface. The UISearchDisplayController allows you to present a standard search interface with born animations. This method forces you to display search results in a table view. - DEPRECATED

  • Using a UISearchController to assist manage a search interface. The UISearchController is a newer controller (available just in iOS 8+) that helps you nowadays a search interface using any kind of view to display the search results.

This guide covers the very nuts of working with each of these classes. None of these classes really implements the "searching" behavior of finding items that lucifer a given query string, since determining which objects lucifer will vary with the domain specific apply case (e.g. when searching for "people" y'all might want to lucifer on just their names, whereas you may want a full-text pre-indexed search when searching through eastward-mails). You lot'll accept to implement any search/filtering behavior yourself.

Working with UISearchBars directly

At its core, a search bar is nothing more than than a glorified text field packaged with a scope command and some animations and a couple of buttons. Each search bar has a delegate that gives you an opportunity to respond to user actions. The almost important delegate methods are:

  • textDidChange - virtually of the fourth dimension you'll answer to this event by updating the displayed set up of search results as the user is typing out a query
  • searchBarSearchButtonClicked - in some cases if the search operation is slow (e.one thousand. requires making a slow API call) y'all'll want to wait until the user taps the search button before updating the search results.

Example searching a tabular array

We showtime out with a single view awarding with a basic UITableView. You can add a UISearchBar as you would with any other control past dragging one to your view controller in interface builder or by programmatically calculation information technology.

The delegate property of search bar must be set to an object that implements UISearchBarDelegate. Typically you make your view controller implement UISearchBarDelegate and fix searchBar.consul = self in viewDidLoad method.

The code to implement the search behavior is as follows. Nosotros maintain an additional assortment filteredData to represent rows of data that match our search text. When the search text changes we update filteredData and reload our table. Find that we use filteredData as the backing array for the table view'south data source. The original data array is our source of truth since filteredData will exist changing constantly.

                      grade            ViewController            :            UIViewController            ,            UITableViewDataSource            ,            UISearchBarDelegate            {            @IBOutlet            weak            var            tableView            :            UITableView            !            @IBOutlet            weak            var            searchBar            :            UISearchBar            !            let            data            =            [            "New York, NY"            ,            "Los Angeles, CA"            ,            "Chicago, IL"            ,            "Houston, TX"            ,            "Philadelphia, PA"            ,            "Phoenix, AZ"            ,            "San Diego, CA"            ,            "San Antonio, TX"            ,            "Dallas, TX"            ,            "Detroit, MI"            ,            "San Jose, CA"            ,            "Indianapolis, IN"            ,            "Jacksonville, FL"            ,            "San Francisco, CA"            ,            "Columbus, OH"            ,            "Austin, TX"            ,            "Memphis, TN"            ,            "Baltimore, Medico"            ,            "Charlotte, ND"            ,            "Fort Worth, TX"            ]            var            filteredData            :            [            String            ]            !            override            func            viewDidLoad            ()            {            super            .            viewDidLoad            ()            tableView            .            dataSource            =            self            searchBar            .            delegate            =            cocky            filteredData            =            data            }            func            tableView            (            _            tableView            :            UITableView            ,            cellForRowAt            indexPath            :            IndexPath            )            ->            UITableViewCell            {            let            cell            =            tableView            .            dequeueReusableCell            (            withIdentifier            :            "TableCell"            ,            for            :            indexPath            )            equally            UITableViewCell            cell            .            textLabel            ?            .            text            =            filteredData            [            indexPath            .            row            ]            return            cell            }            func            tableView            (            _            tableView            :            UITableView            ,            numberOfRowsInSection            section            :            Int            )            ->            Int            {            return            filteredData            .            count            }            // This method updates filteredData based on the text in the Search Box            func            searchBar            (            _            searchBar            :            UISearchBar            ,            textDidChange            searchText            :            String            )            {            // When in that location is no text, filteredData is the same as the original data            // When user has entered text into the search box            // Utilize the filter method to iterate over all items in the data array            // For each particular, return true if the item should be included and simulated if the            // detail should Non exist included            filteredData            =            searchText            .            isEmpty            ?            information            :            data            .            filter            {            (            item            :            Cord            )            ->            Bool            in            // If dataItem matches the searchText, return truthful to include it            return            item            .            range            (            of            :            searchText            ,            options            :            .            caseInsensitive            ,            range            :            nil            ,            locale            :            nil            )            !=            nada            }            tableView            .            reloadData            ()            }            }                  
                      //SearchBarTableViewViewController.h                        @interface            SearchBarTableViewViewController            :            UIViewController            <            UITableViewDelegate            ,            UITableViewDataSource            ,            UISearchBarDelegate            >            @end            //SearchBarTableViewViewController.m                        @interface            SearchBarTableViewViewController            ()            @property            (            potent            ,            nonatomic            )            IBOutlet            UITableView            *            tableView            ;            @property            (            strong            ,            nonatomic            )            NSArray            *            data            ;            @property            (            strong            ,            nonatomic            )            NSArray            *            filteredData            ;            @property            (            stiff            ,            nonatomic            )            IBOutlet            UISearchBar            *            searchBar            ;            @end            @implementation            SearchBarTableViewViewController            -            (            void            )            viewDidLoad            {            [            super            viewDidLoad            ];            self            .            tableView            .            delegate            =            self            ;            self            .            tableView            .            dataSource            =            cocky            ;            cocky            .            searchBar            .            delegate            =            self            ;            self            .            data            =            @[            @"New York, NY"            ,            @"Los Angeles, CA"            ,            @"Chicago, IL"            ,            @"Houston, TX"            ,            @"Philadelphia, PA"            ,            @"Phoenix, AZ"            ,            @"San Diego, CA"            ,            @"San Antonio, TX"            ,            @"Dallas, TX"            ,            @"Detroit, MI"            ,            @"San Jose, CA"            ,            @"Indianapolis, IN"            ,            @"Jacksonville, FL"            ,            @"San Francisco, CA"            ,            @"Columbus, OH"            ,            @"Austin, TX"            ,            @"Memphis, TN"            ,            @"Baltimore, MD"            ,            @"Charlotte, ND"            ,            @"Fort Worth, TX"            ];            cocky            .            filteredData            =            self            .            data            ;            }            -            (            NSInteger            )            tableView            :            (            UITableView            *            )            tableView            numberOfRowsInSection            :            (            NSInteger            )            section            {            return            self            .            filteredData            .            count            ;            }            -            (            UITableViewCell            *            )            tableView            :            (            UITableView            *            )            tableView            cellForRowAtIndexPath            :            (            NSIndexPath            *            )            indexPath            {            UITableViewCell            *            jail cell            =            [            cocky            .            tableView            dequeueReusableCellWithIdentifier            :            @"TableCell"            forIndexPath            :            indexPath            ];            cell            .            textLabel            .            text            =            self            .            filteredData            [            indexPath            .            row            ];            return            cell            ;            }            -            (            void            )            searchBar            :            (            UISearchBar            *            )            searchBar            textDidChange            :            (            NSString            *            )            searchText            {            if            (            searchText            .            length            !=            0            )            {            NSPredicate            *            predicate            =            [            NSPredicate            predicateWithBlock            :            ^            BOOL            (            NSString            *            evaluatedObject            ,            NSDictionary            *            bindings            )            {            return            [            evaluatedObject            containsString            :            searchText            ];            }];            self            .            filteredData            =            [            self            .            data            filteredArrayUsingPredicate            :            predicate            ];            NSLog            (            @"%@"            ,            self            .            filteredData            );            }            else            {            self            .            filteredData            =            self            .            data            ;            }            [            cocky            .            tableView            reloadData            ];            }            @end                  

Here'southward what this looks like when running. Notice that the search results are displayed in the aforementioned table, and in that location is no presentation of a separate search interface.

Example searching a collection view

Since the UISearchBar is quite elementary, it can exist combined with whatever arbitrary view to build your own search interface. Here's what it might look similar paired with a collection view.

The code for this is substantially the same equally in the case with table views.

Cancelling out of Search and hiding keyboard

In one case user taps on search bar, the keyboard volition announced, and y'all will observe that it won't get abroad when you tap on Ten. You lot can show Cancel button when user taps on search bar, and when user taps on Abolish, hide the keyboard.

In that location is a nifty searchBarTextDidBeginEditing method for UISearchBarDelegate that gets called when user starts editing search text. You can show Cancel button in that method:

                      func            searchBarTextDidBeginEditing            (            _            searchBar            :            UISearchBar            )            {            self            .            searchBar            .            showsCancelButton            =            true            }                  
                      -            (            void            )            searchBarTextDidBeginEditing            :(            UISearchBar            *            )            searchBar            {            self            .            searchBar            .            showsCancelButton            =            Yes            ;            }                  

When user taps on abolish button, delegate's searchBarCancelButtonClicked method gets called. At this point, you can hide the Cancel button, clear existing text in search bar and hide the keyboard like this:

                      func            searchBarCancelButtonClicked            (            _            searchBar            :            UISearchBar            )            {            searchBar            .            showsCancelButton            =            false            searchBar            .            text            =            ""            searchBar            .            resignFirstResponder            ()            }                  
                      -            (            void            )            searchBarCancelButtonClicked            :(            UISearchBar            *            )            searchBar            {            cocky            .            searchBar            .            showsCancelButton            =            NO            ;            self            .            searchBar            .            text            =            @""            ;            [            self            .            searchBar            resignFirstResponder            ];            }                  

Using UISearchControllers (iOS eight+)

A newer way to manage the presentation of a search interface (only bachelor in iOS 8 and above) is via the UISearchController. This controller handles some of the logic and animation of presenting a separate search interface for yous while still assuasive yous to specify how your search results are displayed.

Example searching a table

There is currently no congenital-in object in the Interface Builder Object Library for a UISearchController. The easiest way to create one is to exercise it programmatically. This also creates a UISearchBar and sets the search controller'south searchBar holding to information technology. You lot tin add together this search bar to your view hierarchy programmatically.

In order to update your search results yous'll have to implement the UISearchResultsUpdating protocol and ready the search controller's searchResultsUpdater property.

Y'all don't need to implement the UISearchControllerDelegate unless you need to hook into the events effectually the presentation of the search interface.

Putting information technology all together the code looks like this. Observe that we have to read the search text from the search bar in updateSearchResults. Another thing to note is that nosotros set this view controller'due south definesPresentationContext holding to true. This ways the search controller should use this view controller'south frame (as opposed to the root view controller) when presenting the search interface. In this case, the search interface will expand to a higher place the carrier bar.

                      class            ViewController            :            UIViewController            ,            UITableViewDataSource            ,            UISearchResultsUpdating            {            @IBOutlet            weak            var            tableView            :            UITableView            !            allow            data            =            [            "New York, NY"            ,            "Los Angeles, CA"            ,            "Chicago, IL"            ,            "Houston, TX"            ,            "Philadelphia, PA"            ,            "Phoenix, AZ"            ,            "San Diego, CA"            ,            "San Antonio, TX"            ,            "Dallas, TX"            ,            "Detroit, MI"            ,            "San Jose, CA"            ,            "Indianapolis, IN"            ,            "Jacksonville, FL"            ,            "San Francisco, CA"            ,            "Columbus, OH"            ,            "Austin, TX"            ,            "Memphis, TN"            ,            "Baltimore, MD"            ,            "Charlotte, ND"            ,            "Fort Worth, TX"            ]            var            filteredData            :            [            String            ]            !            var            searchController            :            UISearchController            !            override            func            viewDidLoad            ()            {            super            .            viewDidLoad            ()            tableView            .            dataSource            =            self            filteredData            =            data            // Initializing with searchResultsController set to aught means that            // searchController will apply this view controller to display the search results            searchController            =            UISearchController            (            searchResultsController            :            nil            )            searchController            .            searchResultsUpdater            =            self            // If we are using this same view controller to nowadays the results            // dimming information technology out wouldn't make sense. Should probably only set up            // this to yep if using some other controller to brandish the search results.            searchController            .            dimsBackgroundDuringPresentation            =            false            searchController            .            searchBar            .            sizeToFit            ()            tableView            .            tableHeaderView            =            searchController            .            searchBar            // Sets this view controller as presenting view controller for the search interface            definesPresentationContext            =            truthful            }            func            tableView            (            tableView            :            UITableView            ,            cellForRowAtIndexPath            indexPath            :            NSIndexPath            )            ->            UITableViewCell            {            let            cell            =            tableView            .            dequeueReusableCell            (            withIdentifier            :            "TableCell"            )            !            cell            .            textLabel            ?            .            text            =            filteredData            [            indexPath            .            row            ]            return            cell            }            func            tableView            (            tableView            :            UITableView            ,            numberOfRowsInSection            section            :            Int            )            ->            Int            {            return            filteredData            .            count            }            func            updateSearchResults            (            for            searchController            :            UISearchController            )            {            if            allow            searchText            =            searchController            .            searchBar            .            text            {            filteredData            =            searchText            .            isEmpty            ?            information            :            data            .            filter            ({(            dataString            :            String            )            ->            Bool            in            return            dataString            .            rangeOfString            (            searchText            ,            options            :            .            CaseInsensitiveSearch            )            !=            zippo            })            tableView            .            reloadData            ()            }            }            }                  
                      //UISearchViewController.h                        @interface            UISearchViewController            :            UIViewController            <            UITableViewDelegate            ,            UITableViewDataSource            ,            UISearchResultsUpdating            >            @terminate            //UISearchViewController.1000                        @interface            UISearchViewController            ()            @holding            (            strong            ,            nonatomic            )            IBOutlet            UITableView            *            tableView            ;            @property            (            strong            ,            nonatomic            )            UISearchController            *            searchController            ;            @property            (            strong            ,            nonatomic            )            NSArray            *            information            ;            @property            (            strong            ,            nonatomic            )            NSArray            *            filteredData            ;            @end            @implementation            UISearchViewController            -            (            void            )            viewDidLoad            {            [            super            viewDidLoad            ];            self            .            tableView            .            consul            =            self            ;            self            .            tableView            .            dataSource            =            self            ;            cocky            .            information            =            @[            @"New York, NY"            ,            @"Los Angeles, CA"            ,            @"Chicago, IL"            ,            @"Houston, TX"            ,            @"Philadelphia, PA"            ,            @"Phoenix, AZ"            ,            @"San Diego, CA"            ,            @"San Antonio, TX"            ,            @"Dallas, TX"            ,            @"Detroit, MI"            ,            @"San Jose, CA"            ,            @"Indianapolis, IN"            ,            @"Jacksonville, FL"            ,            @"San Francisco, CA"            ,            @"Columbus, OH"            ,            @"Austin, TX"            ,            @"Memphis, TN"            ,            @"Baltimore, MD"            ,            @"Charlotte, ND"            ,            @"Fort Worth, TX"            ];            self            .            filteredData            =            self            .            data            ;            // Initializing with searchResultsController set up to nil ways that                        // searchController will apply this view controller to display the search results                        self            .            searchController            =            [[            UISearchController            alloc            ]            initWithSearchResultsController            :            nil            ];            cocky            .            searchController            .            searchResultsUpdater            =            self            ;            // If we are using this same view controller to present the results                        // dimming it out wouldn't make sense. Should probably only ready                        // this to yes if using another controller to display the search results.                        cocky            .            searchController            .            dimsBackgroundDuringPresentation            =            NO            ;            [            self            .            searchController            .            searchBar            sizeToFit            ];            self            .            tableView            .            tableHeaderView            =            self            .            searchController            .            searchBar            ;            // Sets this view controller every bit presenting view controller for the search interface                        cocky            .            definesPresentationContext            =            YES            ;            }            -            (            NSInteger            )            tableView            :            (            UITableView            *            )            tableView            numberOfRowsInSection            :            (            NSInteger            )            section            {            render            self            .            filteredData            .            count            ;            }            -            (            UITableViewCell            *            )            tableView            :            (            UITableView            *            )            tableView            cellForRowAtIndexPath            :            (            NSIndexPath            *            )            indexPath            {            UITableViewCell            *            cell            =            [            self            .            tableView            dequeueReusableCellWithIdentifier            :            @"TableCell"            forIndexPath            :            indexPath            ];            cell            .            textLabel            .            text            =            self            .            filteredData            [            indexPath            .            row            ];            render            cell            ;            }            -            (            void            )            updateSearchResultsForSearchController            :            (            UISearchController            *            )            searchController            {            NSString            *            searchText            =            searchController            .            searchBar            .            text            ;            if            (            searchText            )            {            if            (            searchText            .            length            !=            0            )            {            NSPredicate            *            predicate            =            [            NSPredicate            predicateWithBlock            :            ^            BOOL            (            NSString            *            evaluatedObject            ,            NSDictionary            *            bindings            )            {            return            [            evaluatedObject            containsString            :            searchText            ];            }];            cocky            .            filteredData            =            [            self            .            data            filteredArrayUsingPredicate            :            predicate            ];            }            else            {            self            .            filteredData            =            cocky            .            data            ;            }            [            cocky            .            tableView            reloadData            ];            }            }            @terminate                  

Hither's what this looks like when running. Notice that different in the search display controller instance, we are using the same table view to brandish the search results instead of overlaying of a separate table view. Yet, dissimilar when working with simply the search bar, we still have the built in animation when transitioning to the search interface.

As well, you lot become the logic to testify Abolish button and hide keyboard when user taps on cancel push for gratuitous when you employ this.

Example searching a collection view

We can just as easily use the search controller to search a collection view in identify. Nosotros nonetheless have the presentation of a search interface, but different when working with the search display controller we are not restricted to using a table view to brandish the search results.

The lawmaking for this is most the same equally when searching the the table view above. The but notable difference is that we had to introduce a placeholder view in interface builder for the search bar since at that place are yet some quirks with placing a search controller'south search bar inside a collection view'southward supplementary view.

                      class            ViewController            :            UIViewController            ,            UICollectionViewDataSource            ,            UISearchResultsUpdating            {            @IBOutlet            weak            var            collectionView            :            UICollectionView            !            @IBOutlet            weak            var            searchBarPlaceholder            :            UIView            !            ...            override            func            viewDidLoad            ()            {            ...            searchController            .            searchBar            .            sizeToFit            ()            searchBarPlaceholder            .            addSubview            (            searchController            .            searchBar            )            automaticallyAdjustsScrollViewInsets            =            false            definesPresentationContext            =            true            }            ...            }                  

Search Bar in Navigation View

A common requirement is to place the search bar within the navigation bar.

This can be configured programmatically in your view controller's viewDidLoad as follows.

When working directly with a search bar:

                      // create the search bar programatically since you won't be            // able to elevate one onto the navigation bar            searchBar            =            UISearchBar            ()            searchBar            .            sizeToFit            ()            // the UIViewController comes with a navigationItem belongings            // this volition automatically be initialized for you if when the            // view controller is added to a navigation controller's stack            // you lot just need to set the titleView to be the search bar            navigationItem            .            titleView            =            searchBar                  
                      // create the search bar programatically since you won't be                        // able to drag one onto the navigation bar                        self            .            searchBar            =            [[            UISearchBar            alloc            ]            init            ];            [            self            .            searchBar            sizeToFit            ];            // the UIViewController comes with a navigationItem property                        // this will automatically be initialized for you if when the                        // view controller is added to a navigation controller'due south stack                        // you merely need to gear up the titleView to be the search bar                        self            .            navigationItem            .            titleView            =            self            .            searchBar            ;                  

Using a search display controller:

                      searchDisplayController            ?            .            displaysSearchBarInNavigationBar            =            true                  

Using a search controller:

                      searchController            .            searchBar            .            sizeToFit            ()            navigationItem            .            titleView            =            searchController            .            searchBar            // By default the navigation bar hides when presenting the            // search interface.  Obviously we don't desire this to happen if            // our search bar is inside the navigation bar.            searchController            .            hidesNavigationBarDuringPresentation            =            simulated                  
                      [            self            .            searchControllerNavi            .            searchBar            sizeToFit            ];            cocky            .            navigationItem            .            titleView            =            self            .            searchControllerNavi            .            searchBar            ;            // By default the navigation bar hides when presenting the                        // search interface.  Obviously we don't want this to happen if                        // our search bar is inside the navigation bar.                        self            .            searchControllerNavi            .            hidesNavigationBarDuringPresentation            =            NO            ;                  

acevedocamond.blogspot.com

Source: https://guides.codepath.com/ios/Search-Bar-Guide

0 Response to "Swift if Text Changes in Search Bar Search Again"

Enviar um comentário

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel