Reputation: 821
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
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
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