ggnoredo
ggnoredo

Reputation: 821

Swift Search Bar with Multiple Data

I have 5 labels that receive data from an array of SQL Query, in each cell on a tableView. I want to implement the search bar on it. Search bar should search through 1 specific label's data. it's working and filtering that specific label but when it's filtered, other 4 labels won't update and they are not changing at all. I can't figure it out. Since I have only 1 filtered data from search bar entry, I don't know how should I filter others. Thanks

EDIT: Still can't figure it out about classes and adding data and i have an error of

"Value of type '[String]' has no member 'localizedCaseInsensitiveContains'"

on searchbar function

import UIKit

class TableViewController: UITableViewController, UISearchBarDelegate, UISearchDisplayDelegate {

var data:[MyData] = []
@IBOutlet weak var searchBar: UISearchBar!
var searchActive : Bool = false
var filtered:[MyData] = []

@IBAction func sqlExecute(_ sender: AnyObject) {

var client = SQLClient()
    client.connect("sql_ip", username: "username", password: "password", database: "database") {
        success in

        if success {
            client.execute("sql query") {
                result in

                for table in result as Any as! NSArray {
                    for row in table as! NSArray {
                        for column in row as! NSDictionary {

                            if column.key as! String == "data1" {
                                MyData.init(data1: "\(column.value)")
                            } else if column.key as! String == "data2" {
                                MyData.init(data2: column.value as! Double)
                            } else if column.key as! String == "data3" {
                                MyData.init(data3: "\(column.value)")
                            } else if column.key as! String == "data4" {
                                MyData.init(data4: "\(column.value)")
                            } else if column.key as! String == "data5" {
                                MyData.init(data5: "\(column.value)")
                            }
                        }
                    }
                }
                client.disconnect()
                self.tableView.reloadData()
            }
        }
    }
}
override func viewDidLoad() {
    super.viewDidLoad()


    tableView.delegate = self
    tableView.dataSource = self
    searchBar.delegate = self
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
}


override func numberOfSections(in tableView: UITableView) -> Int {
    return 1
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if(searchActive) {
        return filtered.count
    } else {
        return data.count
    }
}


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

    if(searchActive) {

        cell.label1.text = "\(filtered[indexPath.row])"
        cell.label2.text = "\(filtered[indexPath.row])"
        cell.label3.text = "\(filtered[indexPath.row])"
        cell.label4.text = "\(filtered[indexPath.row])"
        cell.label5.text = "\(filtered[indexPath.row])"
    } else {

    cell.label1.text = "\(data[indexPath.row])"
    cell.label2.text = "\(data[indexPath.row])"
    cell.label3.text = "\(data[indexPath.row])"
    cell.label4.text = "\(data[indexPath.row])"
    cell.label5.text = "\(data[indexPath.row])"
    }
    cell.backgroundColor = UIColor.clear
    cell.selectionStyle = UITableViewCellSelectionStyle.none
    return cell
}


func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
    searchActive = true;
}

func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
    searchActive = false;
    self.searchBar.endEditing(true)
}

func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
    searchActive = false;
    self.searchBar.endEditing(true)
}

func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
    searchActive = false;
    self.searchBar.endEditing(true)
}

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {

    filtered = data.filter { $0.data1.localizedCaseInsensitiveContains(searchText) }
    if(filtered.count == 0){
        searchActive = false;
    } else {
        searchActive = true;
    }
    self.tableView.reloadData()
}

This is the class file:

import Foundation

class MyData {
var data1 = [String]()
var data2 = [Double]()
var data3 = [String]()
var data4 = [String]()
var data5 = [String]()


init(data1: String) {
    self.data1.append(data1)
}
init(data2: Double) {
    self.data2.append(data2)
}
init(data3: String) {
    self.data3.append(data3)
}
init(data4: String) {
    self.data4.append(data4)
}
init(data5: String) {
    self.data5.append(data5)
}
}

Upvotes: 1

Views: 7334

Answers (2)

Vijayvir Sing Pantlia
Vijayvir Sing Pantlia

Reputation: 689

First you have to make a global array then in search bar delegates sort it .

  extension  HVUserLisitingViewController  : UITableViewDelegate , UITableViewDataSource{

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

       return filterUser.count

    }
 } 
extension HVUserLisitingViewController : UISearchBarDelegate {
    func searchBarShouldBeginEditing(_ searchBar: UISearchBar) -> Bool {
        return true
    }
    func searchBarShouldEndEditing(_ searchBar: UISearchBar) -> Bool {

        return true }
    func searchBar(_ searchBar: UISearchBar, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
        return true
    }
    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) { // called when text changes (including clear)
        webserviceSearchBy(text: searchBar.text!)
    }
    func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
          filterUser.removeAll()
          filterUser = users
          tableview.reloadData()
    }
    func webserviceSearchBy(text : String) {

        if text.lowercased().count == 0 {
            filterUser.removeAll()
            filterUser = users
            tableview.reloadData()
            return
        }
            filterUser.removeAll()

            filterUser = users.filter({ (user) -> Bool in


                if user.username.lowercased().range(of:text.lowercased()) != nil {

                    return true
                }
                return false
            })

            tableview.reloadData()
    }


}

Upvotes: 0

Nirav D
Nirav D

Reputation: 72410

Your problem is you have five different Array instead of that you need to have single Array of type Dictionary or maybe custom Struct/class. It is batter if you use struct/class like this.

class MyData {
    var data1: String!
    var data2: Double!
    var data3: String!
    var data4: String!
    var data5: String! 

    init(data1: String, data2: Double, data3: String, data4: String, data5: String) {
         self.data1 = data1
         self.data2 = data2
         self.data3 = data3
         self.data4 = data4
         self.data5 = data5
    }
}

Now instead of having five different array and one for filter create two Array of type [MyData] one of them is used for showing filterData and use that with tableView methods and filter it like this.

Create object of MyData using init method it and append its to the data Array then filter your in searchBar delegate like this.

filtered = data.filter { $0.data1.localizedCaseInsensitiveContains(searchText) }

The above filter will search in data array and return all objects thats property data1 contains searchText.

Your whole code would be like this

import UIKit

class TableViewController: UITableViewController, UISearchBarDelegate, UISearchDisplayDelegate {

    var data:[MyData] = []

    @IBOutlet weak var searchBar: UISearchBar!
    var searchActive : Bool = false
    var filtered:[MyData] = []


    override func viewDidLoad() {
        super.viewDidLoad()


        tableView.delegate = self
        tableView.dataSource = self
        searchBar.delegate = self
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }


    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if(searchActive) {
            return filtered.count
        } else {
            return data.count
        }
    }


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

        if(searchActive) {

            cell.label1.text = filtered[indexPath.row].data1
            cell.label2.text = filtered[indexPath.row].data2
            cell.label3.text = filtered[indexPath.row].data3
            cell.label4.text = "\(filtered[indexPath.row].data4) ₺"
            cell.label5.text = filtered[indexPath.row].data5
        } else {

            cell.label1.text = data[indexPath.row].data1
            cell.label2.text = data[indexPath.row].data2
            cell.label3.text = data[indexPath.row].data3
            cell.label4.text = "\(data[indexPath.row].data4) ₺"
            cell.label5.text = data[indexPath.row].data5
        }
        cell.backgroundColor = UIColor.clear
        cell.selectionStyle = UITableViewCellSelectionStyle.none
        return cell
    }


    func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
        searchActive = true;
    }

    func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
        searchActive = false;
        self.searchBar.endEditing(true)
    }

    func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
        searchActive = false;
        self.searchBar.endEditing(true)
    }

    func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
        searchActive = false;
        self.searchBar.endEditing(true)
    }

    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {

        filtered = data.filter { $0.data1.localizedCaseInsensitiveContains(searchText) }
        if(filtered.count == 0){
            searchActive = false;
        } else {
            searchActive = true;
        }
        self.tableView.reloadData()
    }
}

Edit: You need to use single array like this way.

for table in result as Any as! NSArray {
    for row in table as! NSArray {
        if let dic = row as? [String : Any] {
            let data1 = dic["data1"] as! String
            let data2 = dic["data2"] as! Double
            let data3 = dic["data3"] as! String
            let data4 = dic["data4"] as! String
            let data5 = dic["data5"] as! String
            let newData =  MyData(data1: data1, data2: data2, data3: data3, data4: data4, data5: data5)
            self.data.append(newData)
        }
    }
}
self.tableView.reloadData()

Upvotes: 3

Related Questions