How to use search bar to fetch data from json result using swift?

9.3k views Asked by At

Requirement : i need to filter the JSON data in UITableView with UISearchBar so i placed UISearchBar (not UISearchBarController) to top of my view controller and i placed UITableView below to the UISearchBarand I also have api key which contains data in json format .

code in my view controller:

 class FourthViewController: UIViewController,UITableViewDelegate,UITableViewDataSource,UISearchBarDelegate,UITabBarControllerDelegate,UISearchDisplayDelegate{
   var arrDict = NSMutableArray()
   var FilteredData = NSMutableArray()
    var userid:String!
    @IBOutlet var SearchButton: UISearchBar!
    @IBOutlet var SlideShow: ImageSlideshow!
    @IBOutlet var MyTableView: UITableView!
    @IBOutlet var PostButton: UIButton!

    override func viewDidLoad() {
    super.viewDidLoad()
     self.navigationController?.navigationBar.hidden = true
     SearchButton.delegate = self

    jsonParsingFromURL()
        SlideShow.backgroundColor = UIColor.whiteColor()
        SlideShow.slideshowInterval = 5.0
        SlideShow.pageControlPosition = PageControlPosition.UnderScrollView
        SlideShow.pageControl.currentPageIndicatorTintColor = UIColor.lightGrayColor()
        SlideShow.pageControl.pageIndicatorTintColor = UIColor.blackColor()
        SlideShow.contentScaleMode = UIViewContentMode.ScaleAspectFill
        SlideShow.setImageInputs(alamofireSource)
           }
func jsonParsingFromURL () {
    if Reachability.isConnectedToNetwork() == true
    {
    Alamofire.request(.GET, "http://something.com", parameters: nil, encoding: .URL, headers: nil).response { (req, res, data, error) -> Void in
        let dataString = NSString(data: data!, encoding:NSUTF8StringEncoding)
        print(dataString)
        self.startParsing(data!)
    }
    }
    else{
        let alert = UIAlertController(title: "No Internet Connection", message: "make sure your device is connected to the internet", preferredStyle: UIAlertControllerStyle.Alert)
        alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil))
        self.presentViewController(alert, animated: true, completion: nil)
    }
}

func startParsing(data :NSData)
{
    let dict: NSDictionary!=(try! NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers)) as! NSDictionary
    for i in 0  ..< (dict.valueForKey("ads") as! NSArray).count
    {
        arrDict.addObject((dict.valueForKey("ads") as! NSArray) .objectAtIndex(i))
    }
    MyTableView.reloadData()
}

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

          return arrDict.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("FirstCell") as! FirstTableViewCell
    let strTitle : NSString=arrDict[indexPath.row] .valueForKey("categoryname") as! NSString
    let photoImage : NSString=arrDict[indexPath.row] .valueForKey("image1") as! NSString
    let SecondImage : NSString=arrDict[indexPath.row] .valueForKey("image2") as! NSString
     let ThirdImage : NSString=arrDict[indexPath.row] .valueForKey("image3") as! NSString
     let FourthImage : NSString=arrDict[indexPath.row] .valueForKey("image4") as! NSString
    let URL_API_HOST2:String = "https://www.imagestring.com/"
  //  let FourthData = NSData(contentsOfURL: NSURL(string: URL_API_HOST2 + (FourthImage as String))!)
    cell.image1.sd_setImageWithURL(NSURL(string: URL_API_HOST2 + (photoImage as String)))
    cell.image2.sd_setImageWithURL(NSURL(string: URL_API_HOST2 + (SecondImage as String)))
         // cell.image2.image = UIImage(data: SecData!)
    cell.image3.sd_setImageWithURL(NSURL(string: URL_API_HOST2 + (ThirdImage as String)))
    cell.image4.sd_setImageWithURL(NSURL(string: URL_API_HOST2 + (FourthImage as String)))
    cell.CategoryName.text = strTitle as String
    return cell
    }

Issue : I have already loaded one api key which is known as category..now i need fetch subcategory data using search bar..subcategory has another api....

1

There are 1 answers

0
dahiya_boy On BEST ANSWER

Apple statement : UISearchController object manages the display of search results based on interactions with a search bar. description here

If you'r using UISearchBar

import UIKit

class TDSearchVC: UIViewController ,UITableViewDataSource,UITableViewDelegate , UISearchResultsUpdating , UISearchBarDelegate{

//MARK:- Outlets
//MARK:-
    @IBOutlet var tblSearch: UITableView!

//MARK:- Properties
//MARK:-

    var dataArray = [String]()
    var filteredArray = [String]()
    var shouldShowSearchResults = false
    var searchController: UISearchController!

//MARK:- VDL
//MARK:-
    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.

        loadListOfCountries() // get the data from file
        configureSearchController() // Config Controller in VC
    }

//MARK:- VC Methods
//MARK:-

    func loadListOfCountries() {
        // Specify the path to the countries list file.
        let pathToFile = Bundle.main.path(forResource: "Country", ofType: "txt")

        if let path = pathToFile {
            // Load the file contents as a string.

            do{
                let countriesString = try String(contentsOfFile: path, encoding: String.Encoding.utf8)
                self.dataArray = countriesString.components(separatedBy: "\n")
            }
            catch{
                print("try-catch error is catched!!")
            }
            tblSearch.reloadData()
        }
    }


    func configureSearchController() {
        searchController = UISearchController(searchResultsController: nil)
        searchController.dimsBackgroundDuringPresentation = false
        searchController.searchBar.placeholder = "Search here..."
        searchController.searchBar.delegate = self
        searchController.searchResultsUpdater = self
        searchController.searchBar.sizeToFit()

        self.tblSearch.tableHeaderView = searchController.searchBar
    }

    //MARK:- table datasource
    //MARK:-

    public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
        if shouldShowSearchResults {
            return filteredArray.count
        }
        else {
            return dataArray.count
        }
    }

    public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as UITableViewCell

        if shouldShowSearchResults {
            cell.textLabel?.text = filteredArray[indexPath.row]
        }
        else {
            cell.textLabel?.text = dataArray[indexPath.row]
        }

        return cell
    }

    //MARK:- search update delegate
    //MARK:-

    public func updateSearchResults(for searchController: UISearchController){
        let searchString = searchController.searchBar.text

        // Filter the data array and get only those countries that match the search text.

        filteredArray = dataArray.filter({ (country) -> Bool in
                    let countryText: NSString = country as NSString
                    return (countryText.range(of: searchString!, options: .caseInsensitive).location) != NSNotFound
                })
        tblSearch.reloadData()
    }

    //MARK:- search bar delegate
    //MARK:-

    public func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
        shouldShowSearchResults = true
        tblSearch.reloadData()
    }


    public func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
        shouldShowSearchResults = false
        tblSearch.reloadData()
    }

}

If you'r using UITextField

import UIKit

class TDSearchVC: UIViewController ,   UITableViewDataSource, UITableViewDelegate, UITextFieldDelegate{


    @IBOutlet var textSearch: UITextField!
    @IBOutlet var tblSearchResult: UITableView!

    var arrData : [String] = []
    var arrFilterData : [String] = []
    var isSearch : Bool!


    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.

        isSearch = false

        /*
         * If date Data is in Json then use JSON Serialization
         */
        arrData = ["Apple", "Banana", "Chikoo", "Brew", "Cherry", "Mango", "Lotus", "Peacock", "Temple", "Pine Apple","Glass", "Rose", "Church", "Computer", "Carrot"]

    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    // MARK:- textfield

    public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool{

        var searchText  = textField.text! + string

        if string  == "" {
            searchText = (searchText as String).substring(to: searchText.index(before: searchText.endIndex))
        }

        if searchText == "" {
            isSearch = false
            tblSearchResult.reloadData()
        }
        else{
            getSearchArrayContains(searchText)
        }

        return true
    }

    // Predicate to filter data
    func getSearchArrayContains(_ text : String) {
        var predicate : NSPredicate = NSPredicate(format: "SELF CONTAINS[c] %@", text)
        arrFilterData = (arrData as NSArray).filtered(using: predicate) as! [String]
        isSearch = true
        tblSearchResult.reloadData()
    }

    // MARK:- TableView Delegates
    public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{

        if isSearch! {
            return arrFilterData.count
        }
        else{

            return arrData.count
        }
    }

    public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{

        var cell : UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "cell")! as UITableViewCell

        if isSearch! {
            cell.textLabel?.text = arrFilterData[indexPath.row]
        }
        else{

            cell.textLabel?.text = arrData[indexPath.row]
        }
        return cell
    }
}