Search code examples
iosjsonswift2tableviewsearchbar

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


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....


Solution

  • 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
        }
    }