Search code examples
uitableviewswiftuisearchbaruisearchdisplaycontrollerxcode6.3

Implement Search bar and search display for the table view with sections


I am trying to implement search bar with search display feature in swift for the table view given below.

Screenshot of the table view

enter image description here

I am getting issue because my string array is in the following format.

["section name1" : ["list1", "list2"] ,"section name2" : ["list3", "list4"]]

I have added my code below for the table view.

    @IBOutlet weak var dishtable: UITableView!

@IBOutlet weak var namlbl: UILabel!
var Dishes = ["POPULAR Dishes": ["Biryani", "Tandori Chicken","Butter Chicken", "Vada Pav"],"A": ["Aloo baingan", "Aloo ki Tikki", "Amritsari fish"], "B": ["Baigan bharta", "Biryani"]];

var Filterval = ["POPULAR Dishes": ["Biryani", "Tandori Chicken","Butter Chicken", "Vada Pav"],"A": ["Aloo baingan", "Aloo ki Tikki", "Amritsari fish"], "B": ["Baigan bharta", "Biryani"]];

struct dish {
    let Dish : [String]
}

override func viewDidLoad() {
    super.viewDidLoad()
    self.dishtable.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell")
    dishtable.dataSource = self
    dishtable.delegate = self
    // Do any additional setup after loading the view.
}


func filterContentForSearchText(searchText: String) {
    // Filter the array using the filter method
    self.Filterval = self.Dishes.filter({( d: dish) -> Bool in
        let DishMatch = (d.Dish == scope)
        let stringMatch = d.Dish.rangeOfString(searchText)
        return DishMatch && (stringMatch != nil)
    })
}

func searchDisplayController(controller: UISearchDisplayController!, shouldReloadTableForSearchString searchString: String!) -> Bool {
    self.filterContentForSearchText(searchString)
    return true
}

func searchDisplayController(controller: UISearchDisplayController!, shouldReloadTableForSearchScope searchOption: Int) -> Bool {
    self.filterContentForSearchText(self.searchDisplayController!.searchBar.text!)
    return true
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}
override func prefersStatusBarHidden() -> Bool {
    return true
}

let sections:Array<AnyObject> = ["POPULAR Dishes","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"]
var usernames = [String]()

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{

    let cellID = "cell"

    let cell: UITableViewCell =  self.dishtable.dequeueReusableCellWithIdentifier(cellID) as! UITableViewCell
    println("value : \(indexPath.section)")
    println("value 1: \(indexPath.row)")
     var d : dish
    if tableView == self.searchDisplayController!.searchResultsTableView {

        cell.textLabel!.text = Filterval[sections[indexPath.section] as! String]![indexPath.row]

    } else {

        cell.textLabel!.text = Dishes[sections[indexPath.section] as! String]![indexPath.row]
    }


    return cell

}

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
    println("Dishes section count : \(section)")
    if tableView == self.searchDisplayController!.searchResultsTableView {
        if section == 0 {
            return Filterval["POPULAR Dishes"]!.count
        }
        else if section == 1 {
            return Filterval["A"]!.count
        }
        else if section == 2 {
            return Filterval["B"]!.count
        }
        else if section == 3 {
            return Filterval["C"]!.count
        }
        else if section == 4 {
            return Filterval["D"]!.count
        }
        else if section == 5 {
            return Filterval["E"]!.count
        }
        else if section == 6 {
            return Filterval["F"]!.count
        }
        return 0
    } else {
    if section == 0 {
        return Dishes["POPULAR Dishes"]!.count
    }
    else if section == 1 {
        return Dishes["A"]!.count
    }
    else if section == 2 {
        return Dishes["B"]!.count
    }
    else if section == 3 {
        return Dishes["C"]!.count
    }
    else if section == 4 {
        return Dishes["D"]!.count
    }
    else if section == 5 {
        return Dishes["E"]!.count
    }
    else if section == 6 {
        return Dishes["F"]!.count
    }
    return 0

    }
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int{

    return 27
}

func tableView(tableView: UITableView, didEndDisplayingCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {

}


func tableView(tableView: UITableView,
    sectionForSectionIndexTitle title: String,
    atIndex index: Int) -> Int{

        return index
}

func tableView(tableView: UITableView,
    titleForHeaderInSection section: Int) -> String?{

        return self.sections[section] as? String
}

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
    tableView.deselectRowAtIndexPath(indexPath, animated: true)

    var ban = ""

    ban = Dishes[sections[indexPath.section] as! String]![indexPath.row]

    println(ban)


}

I have tried the following links online, but unable to implement the search feature.

  1. http://www.ioscreator.com/tutorials/add-search-table-view-tutorial-ios8-swift

  2. http://www.veasoftware.com/tutorials/2015/4/13/search-display-controller-in-swift-xcode-62-ios-82-tutorial

  3. http://www.raywenderlich.com/76519/add-table-view-search-swift

Can someone help me with search bar?


Solution

  • I have made the following changes and got the desired output.

    I am storing my string array in the Core Data with a flag for POPUlAR FOOD in the Core Data and fetching these details and storing in different arrays according to alphabets.

    Created a switch case to show the sections in the table view.

    var distinctstring = [String]()
    var arr = [String]()
    var arrA = [String]()
    var arrB = [String]()
    var arrC = [String]()
    var arrD = [String]()
    var arrE = [String]()
    var arrF = [String]()
    var arrG = [String]()
    var arrH = [String]()
    var arrI = [String]()
    var arrJ = [String]()
    var arrK = [String]()
    var arrL = [String]()
    var arrM = [String]()
    var arrN = [String]()
    var arrV = [String]()
    var arrX = [String]()
    var arrZ = [String]()
    var arrP = [String]()
    var arrO = [String]()
    var arrY = [String]()
    var arrU = [String]()
    var arrT = [String]()
    var arrR = [String]()
    var arrW = [String]()
    var arrQ = [String]()
    var arrS = [String]()
    
    
    var poparr = [String]()
    var filteredTableData = [String]()
    var resultSearchController = UISearchController()
    let collation = UILocalizedIndexedCollation.currentCollation()
        as! UILocalizedIndexedCollation
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        var appDel:AppDelegate = (UIApplication.sharedApplication().delegate as! AppDelegate)
        distinctstring.append("POPULAR FoodS")
        var context: NSManagedObjectContext = appDel.managedObjectContext!
        var request = NSFetchRequest(entityName: "Food")
        var request1 = NSFetchRequest(entityName: "Food")
        if var resultsFood = context.executeFetchRequest(request, error: nil) as? [Food]
        {
            //println("\n Food Results in Table view : \(resultsFood)")
            for resultsb in resultsFood
            {
    
                if (resultsFood.count > 0)
                {
                    println("\(resultsb.Food_name) : \(resultsb.popularity) ")
    
                    if (resultsFood.count > 0)
                    {
                        var firstchar = resultsb.Food_name.substringToIndex(resultsb.Food_name.startIndex.successor())
                        distinctstring.append(firstchar)
                        println("firstchar : \(firstchar)")
                        switch firstchar {
    
                            case "A" :
    
                                arrA.append(resultsb.Food_name)
    
    
                            case "B" :
    
                                arrB.append(resultsb.Food_name)
    
                            case "C" :
    
                                arrC.append(resultsb.Food_name)
    
                            case "D" :
    
                                arrD.append(resultsb.Food_name)
    
                            case "E" :
    
                                arrE.append(resultsb.Food_name)
    
    
                            case "F" :
    
                                arrF.append(resultsb.Food_name)
    
                            case "G" :
    
    
                                arrG.append(resultsb.Food_name)
    
    
                            case "H" :
    
                                arrH.append(resultsb.Food_name)
    
                            case "I" :
    
                                arrI.append(resultsb.Food_name)
    
                            case "J" :
    
                                arrJ.append(resultsb.Food_name)
    
                            case "K" :
    
                                arrK.append(resultsb.Food_name)
    
                            case "L" :
    
                                arrL.append(resultsb.Food_name)
    
                            case "M" :
    
                                arrM.append(resultsb.Food_name)
    
                            case "N" :
    
                                arrN.append(resultsb.Food_name)
    
                            case "O" :
    
                                arrO.append(resultsb.Food_name)
    
                            case "P" :
    
                                arrP.append(resultsb.Food_name)
    
                            case "Q" :
    
                                arrQ.append(resultsb.Food_name)
    
                            case "R" :
    
                                arrR.append(resultsb.Food_name)
    
                            case "S" :
    
                                arrS.append(resultsb.Food_name)
    
                            case "T" :
    
                                arrT.append(resultsb.Food_name)
    
                            case "U" :
    
                                arrU.append(resultsb.Food_name)
    
                            case "V" :
    
                                arrV.append(resultsb.Food_name)
    
                            case "W" :
    
                                arrW.append(resultsb.Food_name)
    
                            case "X" :
    
                                arrX.append(resultsb.Food_name)
    
                            case "Y" :
    
                                arrY.append(resultsb.Food_name)
    
                            case "Z" :
    
                                arrZ.append(resultsb.Food_name)
    
    
    
                            default:
                                println("No present")
                        }
                        arr.append(resultsb.Food_name)
                    }
                }
                else
                {
                    println("No rows found")
    
                }
    
            }
            println("array A = \(arrA)")
            println("array B = \(arrB)")
            println("array C = \(arrC)")
            println("array D = \(arrD)")
            println("array E = \(arrE)")
            println("array F = \(arrF)")
            println("array G = \(arrG)")
            println("array H = \(arrH)")
            println("array I = \(arrI)")
            println("array J = \(arrJ)")
            println("array K = \(arrK)")
            println("array L = \(arrL)")
            println("array M = \(arrM)")
            println("array N = \(arrN)")
            println("array O = \(arrO)")
            println("array P = \(arrP)")
            println("array Q = \(arrQ)")
            println("array R = \(arrR)")
            println("array S = \(arrS)")
            println("array T = \(arrT)")
            println("array U = \(arrU)")
            println("array V = \(arrV)")
            println("array W = \(arrW)")
            println("array X = \(arrX)")
            println("array Y = \(arrY)")
            println("array Z = \(arrZ)")
    
    
           distinctstring = uniq(distinctstring)
    
        }
    
        if var resultsFood1 = context.executeFetchRequest(request1, error: nil) as? [Food]
        {
            //println("\n Food Results in Table view : \(resultsFood)")
            for resultsb in resultsFood1
            {
    
                if (resultsFood1.count > 0)
                {
    
                    //println("\n Table view Results ")
                    //println("Value of Foodname Array : \(resultsb)")
                    if (resultsFood1.count > 0)
                    {
                        if (resultsb.popularity == 1)
                        {    println("Value of pop Foodname Array \(resultsb.Food_name) : \(resultsb.popularity) ")
                            poparr.append(resultsb.Food_name)
                        }
                    }
                }
                else
                {
                    println("No rows found")
    
                }
    
            }
            println("poparr = \(poparr)")
    
        }
    
    
        self.Foodtable.registerClass(UITableViewCell.self, forCellReuseIdentifier: "Cell")
    
        Foodtable.dataSource = self
        Foodtable.delegate = self
        //searchBar.delegate = self
    
        self.resultSearchController = ({
            let controller = UISearchController(searchResultsController: nil)
            controller.searchResultsUpdater = self
            controller.dimsBackgroundDuringPresentation = false
            controller.searchBar.sizeToFit()
            controller.searchBar.placeholder = "Search by Food name"
            self.Foodtable.tableHeaderView = controller.searchBar
    
            return controller
        })()
    
        // Reload the table
        self.Foodtable.reloadData()
        // Do any additional setup after loading the view.
    }
    
    
    
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // 2
        if (self.resultSearchController.active) {
            return self.filteredTableData.count
        }
        else {
    
    
    
            switch distinctstring[section]
            {
    
            case "POPULAR FOOD" :
    
                return self.poparr.count
    
            case "A" :
    
                return self.arrA.count
    
    
            case "B" :
    
                return self.arrB.count
    
            case "C" :
    
                return self.arrC.count
    
            case "D" :
    
                return self.arrD.count
    
            case "E" :
    
                return self.arrE.count
    
    
            case "F" :
    
                return self.arrF.count
    
            case "G" :
    
    
                return self.arrG.count
    
    
            case "H" :
    
                return self.arrH.count
    
            case "I" :
    
                return self.arrI.count
    
            case "J" :
    
                return self.arrJ.count
    
            case "K" :
    
                return self.arrK.count
    
            case "L" :
    
                return self.arrL.count
    
            case "M" :
    
                return self.arrM.count
    
            case "N" :
                return self.arrN.count
            case "O" :
                return self.arrO.count
            case "P" :
                return self.arrP.count
            case "Q" :
                return self.arrQ.count
            case "R" :
                return self.arrR.count
            case "S" :
                return self.arrS.count
            case "T" :
                return self.arrT.count
            case "U" :
                return self.arrU.count
            case "V" :
                return self.arrV.count
            case "W" :
                return self.arrW.count
            case "X" :
                return self.arrX.count
            case "Y" :
                return self.arrY.count
            case "Z" :
                return self.arrZ.count
    
    
            default:
    
                return self.arr.count
    
            }
    
        }
    }
    
    func uniq<S: SequenceType, E: Hashable where E==S.Generator.Element>(source: S) -> [E] {
        var seen: [E:Bool] = [:]
        return filter(source) { seen.updateValue(true, forKey: $0) == nil }
    }
    
    ///////////////////////////////////////Section
    
    func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    
               return (distinctstring.count)
    
    }
    
    
       ///////////////////////////////////////Section
    
    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
    {
        tableView.deselectRowAtIndexPath(indexPath, animated: true)
    
        var dishes = ""
        if (self.resultSearchController.active) {
    
            dishes = filteredTableData[indexPath.row]
    
    
        }
        else {
        println("distinctLetters : \(distinctstring[indexPath.section])")
            switch (distinctstring[indexPath.section]) {
    
    
            case "POPULAR FOOD" :
    
                dishes = poparr[indexPath.row]
    
            case "A" :
    
                dishes = arrA[indexPath.row]
    
            case "B":
    
                dishes = arrB[indexPath.row]
    
            case "C":
    
                dishes = arrC[indexPath.row]
    
            case "D" :
    
                dishes = arrD[indexPath.row]
    
            case "E":
    
                dishes = arrE[indexPath.row]
    
            case "F":
    
                dishes = arrF[indexPath.row]
    
            case "G" :
    
                dishes = arrG[indexPath.row]
    
            case "H":
    
                dishes = arrH[indexPath.row]
    
            case "I":
    
                dishes = arrI[indexPath.row]
    
            case "J" :
    
                dishes = arrJ[indexPath.row]
    
            case "K":
    
                dishes = arrK[indexPath.row]
    
            case "L":
    
                dishes = arrL[indexPath.row]
    
            case "M" :
    
                dishes = arrM[indexPath.row]
    
            case "N":
    
                dishes = arrN[indexPath.row]
    
            case "O":
    
                dishes = arrO[indexPath.row]
    
            case "P" :
    
                dishes = arrP[indexPath.row]
    
            case "Q":
    
                dishes = arrQ[indexPath.row]
    
            case "R":
    
                dishes = arrR[indexPath.row]
    
            case "S" :
    
                dishes = arrS[indexPath.row]
    
            case "T":
    
                dishes = arrT[indexPath.row]
    
            case "U":
    
                dishes = arrU[indexPath.row]
    
            case "V" :
    
                dishes = arrV[indexPath.row]
    
            case "W":
    
                dishes = arrW[indexPath.row]
    
            case "X":
    
                dishes = arrX[indexPath.row]
    
            case "Y" :
    
                dishes = arrY[indexPath.row]
    
            case "Z":
    
                dishes = arrZ[indexPath.row]
                //return sectionHeaderView
            default:
    
                dishes = arr[indexPath.row]
            }
    
    
    
        }
        println("row selected : \(dishes)")
    }
    
    func tableView(tableView: UITableView,titleForHeaderInSection section: Int) -> String?{
    
        if (self.resultSearchController.active) {
    
    
            return ""
        }
        else {
                 return "\(distinctstring[section])"
        }
    
        }
    
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    
        let cell = tableView.dequeueReusableCellWithIdentifier("Cell") as! UITableViewCell;
        cell.textLabel!.font = UIFont(name: "Gotham", size: 13)
    
        //println("distinctLetters in cell : \(distinctLetters[indexPath.section]) ")
        cell.textLabel!.numberOfLines = 2;
        if (self.resultSearchController.active) {
            cell.textLabel?.text = filteredTableData[indexPath.row]
    
            return cell
        }
        else {
    
    
            switch (distinctstring[indexPath.section]) {
    
            case "POPULAR FOOD" :
    
                cell.textLabel?.text = poparr[indexPath.row]
            case "A" :
    
                cell.textLabel?.text = arrA[indexPath.row]
    
            case "B":
    
                cell.textLabel?.text = arrB[indexPath.row]
    
            case "C":
    
                cell.textLabel?.text = arrC[indexPath.row]
    
            case "D" :
    
                cell.textLabel?.text = arrD[indexPath.row]
    
            case "E":
    
                cell.textLabel?.text = arrE[indexPath.row]
    
            case "F":
    
                cell.textLabel?.text = arrF[indexPath.row]
    
            case "G" :
    
                cell.textLabel?.text = arrG[indexPath.row]
    
            case "H":
    
                cell.textLabel?.text = arrH[indexPath.row]
    
            case "I":
    
                cell.textLabel?.text = arrI[indexPath.row]
    
            case "J" :
    
                cell.textLabel?.text = arrJ[indexPath.row]
    
            case "K":
    
                cell.textLabel?.text = arrK[indexPath.row]
    
            case "L":
    
                cell.textLabel?.text = arrL[indexPath.row]
    
            case "M" :
    
                cell.textLabel?.text = arrM[indexPath.row]
    
            case "N":
    
                cell.textLabel?.text = arrN[indexPath.row]
    
            case "O":
    
                cell.textLabel?.text = arrO[indexPath.row]
    
            case "P" :
    
                cell.textLabel?.text = arrP[indexPath.row]
    
            case "Q":
    
                cell.textLabel?.text = arrQ[indexPath.row]
    
            case "R":
    
                cell.textLabel?.text = arrR[indexPath.row]
    
            case "S" :
    
                cell.textLabel?.text = arrS[indexPath.row]
    
            case "T":
    
                cell.textLabel?.text = arrT[indexPath.row]
    
            case "U":
    
                cell.textLabel?.text = arrU[indexPath.row]
    
            case "V" :
    
                cell.textLabel?.text = arrV[indexPath.row]
    
            case "W":
    
                cell.textLabel?.text = arrW[indexPath.row]
    
            case "X":
    
                cell.textLabel?.text = arrX[indexPath.row]
    
            case "Y" :
    
                cell.textLabel?.text = arrY[indexPath.row]
    
            case "Z":
    
                cell.textLabel?.text = arrZ[indexPath.row]
                //return sectionHeaderView
            default:
    
                cell.textLabel?.text = arr[indexPath.row]
            }
    
            return cell
        }Food
        //return cell;
    }
    
    
       func updateSearchResultsForSearchController(searchController: UISearchController)
    {
        filteredTableData.removeAll(keepCapacity: false)
    
        let searchPredicate = NSPredicate(format: "SELF CONTAINS[c] %@", searchController.searchBar.text)
        let array = (arr as NSArray).filteredArrayUsingPredicate(searchPredicate)
        filteredTableData = array as! [String]
    
        self.Foodtable.reloadData()
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    override func prefersStatusBarHidden() -> Bool {
        return true
    }
    
    
    
    }