search in retrieved data from json in swift3 - swift

I retrieve data from service URL in swift3 and displayed in tableview. I tried to search names, it shows filtered names but another cell is not updating. please check my below code.
class MyViewController: UIViewController,UITableViewDataSource,UITableViewDelegate,UISearchBarDelegate {
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var searchBar: UISearchBar!
var filteredArray = [String]()
var shouldShowSearchResults = false
var nameArray = [String]()
var emailArray = [String]()
var tableData = [String]()
override func viewDidLoad() {
super.viewDidLoad()
downloadData()
createSearchBar()
// Do any additional setup after loading the view.
}
func createSearchBar(){
searchBar.showsCancelButton = false
searchBar.placeholder = "Enter your search"
searchBar.delegate = self
self.navigationItem.titleView = searchBar
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
tableData = nameArray
if shouldShowSearchResults
{
return filteredArray.count
}
else
{
return tableData.count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell:mycell! = tableView.dequeueReusableCell(withIdentifier: "cell") as! mycell
if shouldShowSearchResults
{
cell.name.text = filteredArray[indexPath.row]
cell.email.text = emailArray[indexPath.row]
return cell
}
else
{
cell.name.text = tableData[indexPath.row]
cell.email.text = emailArray[indexPath.row]
return cell
}
}
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
searchBar.endEditing(true)
}
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
shouldShowSearchResults = true
searchBar.endEditing(true)
self.tableView.reloadData()
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
filteredArray = tableData.filter({
(names:String) -> Bool in
return names.lowercased().range(of: searchText.lowercased()) != nil
})
if searchText != ""
{
shouldShowSearchResults = true
self.tableView.reloadData()
}
else
{
shouldShowSearchResults = false
self.tableView.reloadData()
}
}
func downloadData()
{
let url = URL(string: "http://www.json-generator.com/api/json/get/crdvbKvLoy?indent=2")!
var request = URLRequest(url: url, cachePolicy: .reloadIgnoringCacheData, timeoutInterval: 10000)
URLSession.shared.dataTask(with: request) { (data, response, error) in
if error != nil {
print(error!)
return
}
do {
if let jsonData = try JSONSerialization.jsonObject(with:data!, options: []) as? [[String:AnyObject]] {
print(jsonData)
// Utility.SharedInstance.dict_UserDetails3 = jsonData as AnyObject
for item in jsonData {
if let name = item["Name"] as? AnyObject {
self.nameArray.append(name as! String)
}
if let email = item["Email"] as? AnyObject{
self.emailArray.append(email as! String)
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
}
} catch let error as NSError {
print(error)
}
}.resume()
}
}
output:
search___________
Name Email
----------------
Wasim wasim#gmail.com
Dravid dravid#gmail.com
Kohli virat#gmail.com
Kallis Jaques#gmail.com
I entered in search text as K
-----------------------------
search_____K______
Name Email
----------------
Kohli wasim#gmail.com
Kallis dravid#gmail.com
In this search works, but Email field not updating. please check once. I am tried more samples but not solved. please check once, what changes I do to solve this problem.

you filter name array but not the email address array. so the indexes don't match up.
The best solution is to not separate related data. Structure it properly.
struct Person {
var name: String
var email: String
}
var people: [Person]?
var filteredResults: [Person]?
Using a struct for a person that holds the name and email together, you can filter this array easier and the data wont get out of sync.

Related

How to Increase count of Page in Url for loading more data and show indicator at bottom?

I Creating a demo of webservices, In this I want to increase page count and load more data from api, and add in table view after activity indicator refreshing. I find many tutorials but Not found useful... They are all Advance and I'm beginner so i didn't get properly. Can Any one please tell how to do this.
Here's My Demo details...
This Is Page Count of URL
"info": {
"count": 826,
"pages": 42,
"next": "https://rickandmortyapi.com/api/character/?page=3",
"prev": "https://rickandmortyapi.com/api/character/?page=1"
},
My json Model
import UIKit
import Foundation
// MARK: - JsonModel
struct JSONModel:Decodable {
let info: Info
let results: [Result]
}
// MARK: - Info
struct Info : Decodable {
let count, pages: Int
let next: String
let prev: NSNull
}
// MARK: - Result
struct Result : Decodable {
let id: Int
let name: String
let status: Status
let species: Species
let type: String
let gender: Gender
let origin, location: Location
let image: String
let episode: [String]
let url: String
let created: String
}
enum Gender {
case female
case male
case unknown
}
// MARK: - Location
struct Location {
let name: String
let url: String
}
enum Species {
case alien
case human
}
enum Status {
case alive
case dead
case unknown
}
This is my View controller Class
import UIKit
import Kingfisher
class ViewController: UIViewController,UISearchBarDelegate{
#IBOutlet weak var searchBar: UISearchBar!
#IBOutlet weak var tableView: UITableView!
var results = [Results]()
var filteredData = [Results]()
var batchSize = 42
var fromIndex = 0
override func viewDidLoad() {
super.viewDidLoad()
searchBar.delegate = self
tableView.delegate = self
tableView.dataSource = self
apiCalling()
filteredData = results
}
override func viewWillAppear(_ animated: Bool) {
filteredData = results
self.tableView.reloadData()
}
func apiCalling(){
guard let url = URL(string: "https://rickandmortyapi.com/api/character/") else { return }
URLSession.shared.dataTask(with: url) {[weak self]data, response, error in
if error != nil{
print("error While Fetching Data")
}
guard let data = data else {
return
}
do {
let resultData = try JSONDecoder().decode(JsonModel.self, from: data)
self?.results = resultData.results!
self?.filteredData = self!.results
DispatchQueue.main.async {
self?.tableView.reloadData()
}
} catch {
print(error.localizedDescription)
}
}.resume()
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
let searchText = searchBar.text!
guard !searchText.isEmpty else {
filteredData = results
tableView.reloadData()
return
}
filteredData = results.filter({ $0.name!.lowercased().contains(searchText.lowercased() ) })
tableView.reloadData()
}
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
self.searchBar.showsCancelButton = true
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
searchBar.showsCancelButton = false
searchBar.text = ""
searchBar.resignFirstResponder()
filteredData.removeAll()
self.tableView.reloadData()
}
}
This My Tableview Extension
extension ViewController : UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return filteredData.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! UserTableViewCell
let row = filteredData[indexPath.row]
let imageUrl = URL(string: row.image!)
cell.userImage.kf.setImage(with: imageUrl)
cell.lblGender.text = "Gender:- \(row.gender ?? "no value")"
cell.lblID.text = "ID:- \(row.id ?? 0)"
cell.lblName.text = "Name: \(row.name!)"
cell.lblSpecies.text = "Species:- \(row.species ?? "No Speies")"
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return 250
}
}
u need save page info.
self?.info = resultData.info!
call "loadpage" when u loading more data
override func viewDidLoad() {
super.viewDidLoad()
searchBar.delegate = self
tableView.delegate = self
tableView.dataSource = self
filteredData = []
result = []
apiCalling(apiurl:"https://rickandmortyapi.com/api/character/")
}
func apiCalling(apiurl:String){
guard let url = URL(string: apiurl) else { return }
URLSession.shared.dataTask(with: url) {[weak self]data, response, error in
if error != nil{
print("error While Fetching Data")
}
guard let data = data else {
return
}
do {
let resultData = try JSONDecoder().decode(JsonModel.self, from: data)
self?.results.append(resultData.results!)
self?.info = resultData.info!
filterWord()
} catch {
print(error.localizedDescription)
}
}.resume()
}
func filterWord(){
let searchText = searchBar.text!
guard !searchText.isEmpty else {
filteredData = results
tableView.reloadData()
return
}
filteredData = results.filter({ $0.name!.lowercased().contains(searchText.lowercased() ) })
tableView.reloadData()
}
func loadPage(){
guard let page = self?.info.next,!page.isEmpty else{
return
}
apiCalling(apiurl:page)
}
under indicator simple example like this
func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
guard let page = self?.info.next,!page.isEmpty else{
return nil
}
//press to call loadPage
let loading = UIButton.init()
let view = UIView.init()
view.addSubview(loading)
return view
}
I'm Giving My own Questions answer Here...
I Have Create 3 more variables
var curentIndex : Int = 0
// I'm Putting Default Limit Here...
var numberArray = Array(1...42)
var fetchingMore = false
Api Call
func apiCalling(){
guard !fetchingMore else {
print("Didn't call Get Data")
return
}
fetchingMore = true
guard let url = URL( string: "\(baseUrl)?page=\(numberArray[curentIndex])") ?? URL(string: "" ) else {
fetchingMore = false
return
}
curentIndex += 1
URLSession.shared.dataTask(with: url) {[weak self]data, response, error in
if error != nil{
print("error While Fetching Data")
}
guard let data = data else {
return
}
do {
let resultData = try JSONDecoder().decode(JsonModel.self, from: data)
self?.results += resultData.results!
self?.filteredData = self!.results
DispatchQueue.main.async {
self?.tableView.reloadData()
}
} catch {
print(error.localizedDescription)
}
self?.fetchingMore = false
}.resume()
}
**Here's My CellForRowMethod **
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! UserTableViewCell
let row = filteredData[indexPath.row]
if indexPath.row == filteredData.count - 1 && curentIndex <= row.id ?? 0 {
apiCalling()
}
let imageUrl = URL(string: row.image!)
cell.userImage.kf.setImage(with: imageUrl)
cell.lblGender.text = "Gender:- \(row.gender ?? "no value")"
cell.lblID.text = "ID:- \(row.id ?? 0)"
cell.lblName.text = "Name: \(row.name!)"
cell.lblSpecies.text = "Species:- \(row.species ?? "No Speies")"
return cell
}

SearchBar doesn't returns results until activated and typing

I see empty rows when my tableView is loaded for the first time. But if I activate searchBar, write something into textField everything works correctly even i clean all the text. I want the app works without these extra steps. But I don't understand where exactly I am making the mistake.
class NextTableViewCell: UITableViewController, UISearchBarDelegate, UISearchControllerDelegate {
#IBOutlet weak var searchBar: UISearchBar!
var ref: DatabaseReference?
let db = Firestore.firestore()
var messages: [Message] = []
var filteredMessages: [Message] = []
override func viewDidLoad() {
super.viewDidLoad()
searchBar.delegate = self
tableView.dataSource = self
loadMessages()
filteredMessages = messages
}
Func loadMessages retrieves data from Firebase
func loadMessages() {
let user = Auth.auth().currentUser?.email
let docRef = db.collection(K.FStore.collectionName).document(user!)
docRef.addSnapshotListener { (querySnapshot, error) in
self.messages = []
if let e = error {
print(e)
} else {
if let snapshotDocuments = querySnapshot?.data(){
for item in snapshotDocuments {
if let key = item.key as? String, let translate = item.value as? String {
let newMessage = Message(key: key, value: translate)
self.messages.append(newMessage)
}
}
DispatchQueue.main.async { [self] in
self.messages.sort(by: {$1.key > $0.key})
self.tableView.reloadData()
}
}
}
}
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return filteredMessages.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let message = filteredMessages[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "ListVC", for: indexPath)
cell.textLabel?.text = message.key + " - " + message.value
return cell
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
filteredMessages = []
if searchText == "" {
filteredMessages = messages
}else{
for item in messages {
if item.key.lowercased().contains(searchText.lowercased()){
if let key = item.key as? String, let translate = item.value as? String {
let newMessage = Message(key: key, value: translate)
self.filteredMessages.append(newMessage)
}
}
}
}
tableView.reloadData()
}
The problem is that filteredMessages is empty when the view controller loads and only gets populated when you search.
Since filteredMessages is essentially a subset of messages, you need to set filteredMessages to messages upon fetching them from the database.
Try adding a line that does that in your loadMessages() method:
DispatchQueue.main.async { [self] in
self.messages.sort(by: {$1.key > $0.key})
self.filteredMessages = self.messages // Add this line
self.tableView.reloadData()
}

Swift Error with (outlets, keyPath, key value and UITableViewCellContentView)

I'm new to swift and I was just working on this program that has a table view with a list of names that the user can search through. It was working fine, until I tried to implement a UISearchbar and it gave me the error
Failed to set (keyPath) user defined inspected property on (UITableViewCellContentView): [<UITableViewCellContentView 0x7fb4624048c0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key keyPath.
I've done some research and I'm figured out that this error normally occurs when there is a problem with IB Outlets, but my outlets seem to be doing fine and this is what they look like-
Photo of my Outlet Connections
If you think there might be a problem in my code- here it is (Sorry it is messy):
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate {
func searchBarShouldEndEditing(_ searchBar: UISearchBar) -> Bool {
if searchBar.text == "" {
searchBar.placeholder = "Enter Name"
return true
} else {
return true
}
}
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
searchBar.endEditing(true)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if searching == true {
return searchingPeople.count
} else {
return people.count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tblView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
if searching == true {
cell.textLabel?.text = searchingPeople[indexPath.row]
} else {
cell.textLabel?.text = people[indexPath.row]
}
return cell
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
searchingPeople = people.filter({$0.lowercased().prefix(searchText.count) == searchText.lowercased()})
searching = true
tblView.reloadData()
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
view.endEditing(true)
searching = false
searchBar.text = ""
tblView.reloadData()
}
var people: [String] = []
var searchingPeople = [String()]
var searching = false
#IBOutlet weak var tblView: UITableView!
#IBOutlet weak var searchBar: UISearchBar!
override func viewDidLoad() {
super.viewDidLoad()
tblView.delegate = self
tblView.dataSource = self
searching = false
searchBar.text = ""
guard let path = Bundle.main.path(forResource: "finalDataPapa", ofType: "json") else { return }
let url = URL(fileURLWithPath: path)
do {
let data = try Data(contentsOf: url)
let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers)
// print(json)
guard let array = json as? [Any] else { return }
//38104 people
var i: Int = 1
while i < 38104 {
guard let personDict = array[i] as? [String: Any] else { return }
guard let personfName = personDict["FIRST NAME"] as? String else { print("Persons name in numbers"); return }
guard let personlName = personDict["LAST NAME"] as? String else { print("Persons name in numbers"); return }
//guard let personmName = personDict["MIDDLE"] as? String else { print("Persons name in numbers"); return }
let fullName = "\(personfName) \(personlName)"
people.append(fullName)
i = i + 1
}
DispatchQueue.main.async {
self.tblView.reloadData()
}
}
catch {
print(error)
}
class People: Decodable {
let LASTNAME: String?
let FIRSTNAME: String?
let MIDDLE: String?
enum CodingKeys: String, CodingKey {
case FIRSTNAME = "FIRST NAME"
case LASTNAME = "LAST NAME"
case MIDDLE = "MIDDLE"
}
}
}
}

Dictionary search the key and get the value

I got a plist object which contains all the words key=english and value=malay and I assigned in to 2 different arrays which is english and malay. Now I want a textfield where I want to search the english word and print the malay word in the label.
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, UITextFieldDelegate {
#IBOutlet weak var selectedLabel: UILabel!
#IBOutlet weak var searchText: UITextField!
#IBOutlet weak var wordTable: UITableView!
var english = [String]()
var malay = [String]()
var words: [String: String] = [:]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
wordTable.dataSource = self
wordTable.delegate = self
searchText.delegate = self
if let path = Bundle.main.path(forResource: "words", ofType: "plist"){
if let plistData = FileManager.default.contents(atPath: path){
do {
let plistObject = try PropertyListSerialization.propertyList(from: plistData, options: PropertyListSerialization.ReadOptions(), format: nil)
words = (plistObject as? [String: String])!
english = [String] (words.keys)
malay = [String] (words.values)
} catch {
print("Error Serialize")
}
} else {
print("Error reading data")
}
} else {
print("Property list")
}
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return english.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell: UITableViewCell!
cell = tableView.dequeueReusableCell(withIdentifier: "tabelCell")
if cell == nil {
cell = UITableViewCell(
style: UITableViewCellStyle.value2,
reuseIdentifier: "tableCell")
print("creating a table cell")
}
cell!.textLabel!.text = english[indexPath.row]
cell!.detailTextLabel?.text = malay[indexPath.row]
return cell!
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
selectedLabel.text = malay[indexPath.row]
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
// Hide the keyboard
textField.resignFirstResponder()
return true
}
#IBAction func searchBtn(_ sender: UIButton) {
let result = words.filter {$0.key == searchText.text}
if result.count > 0 {
print(result)
selectedLabel.text! = result.values //error
} else {
print("Not found")
}
}
}
the output I expecting is textfield(Bus) which is english word then in the label show me the malay word(Bas)
You have a plist file as a Dictionary. So you can get the dictionary object from the plist file and already answer here.
Make a structure for better data binding.
struct Word {
var english: String
var malay: String
}
Then declare an array of words globally in your ViewController.
var words: [Word] = [] // An empty array
In viewDidLoad: fetch data from plist file.
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
wordTable.dataSource = self
wordTable.delegate = self
searchText.delegate = self
if let path = Bundle.main.path(forResource: "words", ofType: "plist") {
if let plistData = FileManager.default.contents(atPath: path){
do {
guard let plistObject = try PropertyListSerialization.propertyList(from: plistData, options: [], format: nil) as? [String: String] else {
// Plist is not [String: String]
return
}
// Here you need to change the code. Converting the dictionary into struct array
var words: [Word] = plistObject.map {Word(english: $0.key, malay: $0.value)}
/// Then sort by english word if needed
words.sorted {$0.english < $1.english}
} catch {
print("Error Serialize")
}
} else {
print("Error reading data")
}
} else {
print("Property list")
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return words.count
}
Update your cell data as well.
cell!.textLabel!.text = words[indexPath.row].english
cell!.detailTextLabel?.text = words[indexPath.row].malay
And your button action with minor modification:
#IBAction func searchBtn(_ sender: UIButton) {
let result = words.filter {$0.english == searchedText}
if let word = result.first {
selectedLabel.text = word.malay
} else {
selectedLabel.text = "" // No data found
}
}
You can replace $0.english == searchedText with {$0.english.contains(searchedText)} if you want to filter with contains, But in that case you might get the multiple result. I assume that in your case you need it as a translator so use ==.
Why don't you search in your plist object? I think it is simpler
#IBAction func searchBtn(_ sender: UIButton) {
guard let words = plistObject as? [String: String], let key = searchText.text else { return }
selectedLabel.text = words[key] ?? ""
}
Something like this.

Swift 3 table search

I have populated a table using json data from a remote server.
I am now trying to add a search bar which will filter the results.
The issue I am facing is that I am storing the json data in several arrays.
name, company, job title etc
This means that when the user searches only the name array is filtered and displayed in the table correctly, the other information is out of sync as it remains unfiltered.
Am I approaching this in the correct way?
class attendees: UIViewController, UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate {
var tableData = ""
var value:String!
var searchString = ""
var firstname: [String] = []
var lastname: [String] = []
var fullname: [String] = []
var company: [String] = []
var jobtitle: [String] = []
var image: [String] = []
var filteredAppleProducts = [String]()
var resultSearchController = UISearchController()
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var searchBar: UISearchBar!
override func viewDidLoad() {
print(value)
searchBar.delegate = self
self.tableView.reloadData()
let nib = UINib(nibName: "vwTblCell2", bundle: nil)
tableView.register(nib, forCellReuseIdentifier: "cell2")
}
override func viewDidAppear(_ animated: Bool) {
getTableData()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if filteredAppleProducts != []{
return self.filteredAppleProducts.count
}
else
{
if searchString != "[]" {
return self.firstname.count
}else {
return 0
}
}
}
// 3
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell2: TblCell2 = self.tableView.dequeueReusableCell(withIdentifier: "cell2") as! TblCell2
print(filteredAppleProducts)
if filteredAppleProducts != []{
cell2.nameLabel.text = self.filteredAppleProducts[indexPath.row]
return cell2
}
else
{
if searchString != "[]"{
cell2.nameLabel.text = "\(self.firstname[indexPath.row]) \(self.lastname[indexPath.row])"
cell2.companyLabel.text = self.company[indexPath.row]
cell2.jobTitleLabel.text = self.jobtitle[indexPath.row]
let url = URL(string: "https://www.asmserver.co.uk/wellpleased/backend/profileimages/\(self.image[indexPath.row])")
let data = try? Data(contentsOf: url!) //make sure your image in this url does exist, otherwise unwrap in a if let check / try-catch
cell2.userImage.image = UIImage(data: data!)
}
return cell2
}
}
// 4
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
}
// 5
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 90
}
func updateSearchResults(){
self.filteredAppleProducts.removeAll(keepingCapacity: false)
let searchPredicate = NSPredicate(format: "SELF CONTAINS[c] %#", searchString)
let array = (self.fullname as NSArray).filtered(using: searchPredicate)
self.filteredAppleProducts = array as! [String]
self.tableView.reloadData()
print(filteredAppleProducts)
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
print("searchText \(searchText)")
print(filteredAppleProducts)
searchString = searchText
updateSearchResults()
}
func getTableData(){
self.firstname.removeAll()
self.lastname.removeAll()
self.fullname.removeAll()
self.company.removeAll()
self.jobtitle.removeAll()
self.image.removeAll()
let defaults = UserDefaults()
let userid = defaults.string(forKey: "id")
let url = NSURL(string: "https://www.asmserver.co.uk/wellpleased/backend/searchattendees.php?userid=\(userid!)&eventid=\(value!)")
print(url)
let task = URLSession.shared.dataTask(with: url as! URL) { (data, response, error) -> Void in
if let urlContent = data {
do {
if let jsonResult = try JSONSerialization.jsonObject(with: urlContent, options: []) as? [[String:AnyObject]] {
var i = 0
while i < jsonResult.count {
self.firstname.append(jsonResult[i]["firstname"]! as! String)
self.lastname.append(jsonResult[i]["lastname"]! as! String)
let fname = jsonResult[i]["firstname"]! as! String
let lname = jsonResult[i]["lastname"]! as! String
let fullname1 = "\(fname) \(lname)"
self.fullname.append(fullname1)
self.company.append(jsonResult[i]["company"]! as! String)
self.jobtitle.append(jsonResult[i]["jobtitle"]! as! String)
self.image.append(jsonResult[i]["image"]! as! String)
i = i + 1
}
}
} catch {
print("JSON serialization failed")
}
} else {
print("ERROR FOUND HERE")
}
DispatchQueue.main.async(execute: { () -> Void in
self.tableView.reloadData()
})
self.tableView.isUserInteractionEnabled = true
}
task.resume()
}
}
Use a struct or class for the data. This way it'll be easier to keep track of the data, and in any case it looks like you don't have any good reason to keep track of seven different arrays.
As an example:
struct Data {
var firstName: String
var lastName: String
var fullName: String
var company: String
var jobTitle: String
var image: String
}
And populate just the one array:
var dataSource: [Data] = []
Access with property name, instead of arrayName[index]:
let name = dataSource[index].firstName