What is wrong with my UISearchBar result? - swift

I have parsed a JSON using Alamofire and SwiftyJSON to get a list of the names of cryptocurrencies and populate a table view. I then am trying to filter the results using a UISearchBar, but whatever I search, it always shows the first result of the array of names, even though the filter is working as I tested it using print and it correctly filters. for example, i search for Ethereum and the console prints ["name": "Ethereum"] but the Tableview will show "Bitcoin" always, if i search a name that doesn't exist, it shows nothing. Can anyone identify what is wrong in my code that causes this problem? Thank you very much, I am new to any kind of coding.
here is my code:
//
// StartViewController.swift
// CryptoClockTesting
//
// Created by Peter Ruppert on 08/07/2018.
// Copyright © 2018 Peter Ruppert. All rights reserved.
//
import UIKit
import Alamofire
import SwiftyJSON
class StartViewController: UIViewController, UISearchBarDelegate,
UITableViewDelegate, UITableViewDataSource {
var names = [[String:String]]()
var isSearching = false
var filteredData = [[String:String]]()
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var searchBar: UISearchBar!
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
let name = names[indexPath.row]
let text: [String:String]
if isSearching {
text = filteredData[indexPath.row]
print(text)
} else {
text = name
}
cell.textLabel?.text = name["name"]
cell.textLabel?.textColor = UIColor.blue
return cell
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
if searchBar.text == nil || searchBar.text == "" {
isSearching = false
view.endEditing(true)
tableView.reloadData()
} else {
isSearching = true
filteredData = names.filter({
$0["name"] == searchBar.text
})
tableView.reloadData()
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if isSearching {
return filteredData.count
} else {
return names.count
}
}
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
tableView.isHidden = false
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
tableView.isHidden = true
}
override func viewDidLoad() {
super.viewDidLoad()
tableView.isHidden = true
searchBar.delegate = self
tableView.delegate = self
tableView.dataSource = self
searchBar.returnKeyType = UIReturnKeyType.done
self.view.backgroundColor = .blue
let urlString = "https://api.coingecko.com/api/v3/coins"
if let url = URL(string: urlString) {
if let data = try? String(contentsOf: url) {
let json = JSON(parseJSON: data)
parse(json: json)
}
}
}
//Parsing News API and adding to table, then use table view setup to properly display.
func parse(json: JSON) {
for result in json[].arrayValue {
let name = result["name"].stringValue
let obj = ["name": name]
names.append(obj)
}
tableView.reloadData()
}
}

This because you always set it to name["name"] in cellForRowAt
if isSearching {
text = filteredData[indexPath.row]
print(text)
} else {
text = name
}
cell.textLabel?.text = name["name"] // should be text["name"]

Related

Search bar isn't working and selection is gray (I want to be None)

My search bar isn't working and I'm not sure why. I followed a tutorial online. There is a picture of my find friends view controller below and the code for the view controller.
Also even though in my storyboard selection is set to "None" it is gray on ios.
Not sure how to fix the selection part. Search bar fixed and solution is in comments below.
import UIKit
class FindFriendsViewController: UIViewController {
var users = [User]()
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var searchBar: UISearchBar!
var searchItem = [String]()
var searching = false
override func viewDidLoad() {
super.viewDidLoad()
tableView.tableFooterView = UIView()
tableView.rowHeight = 71
let tap = UITapGestureRecognizer(target: self.view, action: #selector(UIView.endEditing(_:)))
tap.cancelsTouchesInView = false
self.view.addGestureRecognizer(tap)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
UserService.usersExcludingCurrentUser { [unowned self] (users) in
self.users = users
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
}
}
extension FindFriendsViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
var usernamesArr = [String]()
for user in users {
usernamesArr.append(user.username)
}
if searching {
return searchItem.count
} else {
return usernamesArr.count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "FindFriendsCell") as! FindFriendsCell
let user = users[indexPath.row]
var usernamesArr = [String]()
for user in users {
usernamesArr.append(user.username)
}
if searching {
cell.usernameLabel?.text = searchItem[indexPath.row]
} else {
cell.usernameLabel?.text = usernamesArr[indexPath.row]
cell.delegate = self
configure(cell: cell, atIndexPath: indexPath)
}
return cell
}
func configure(cell: FindFriendsCell, atIndexPath indexPath: IndexPath) {
let user = users[indexPath.row]
cell.usernameLabel.text = user.username
cell.followButton.isSelected = user.isFollowed
}
}
extension FindFriendsViewController: FindFriendsCellDelegate {
func didTapFollowButton(_ followButton: UIButton, on cell: FindFriendsCell) {
guard let indexPath = tableView.indexPath(for: cell) else { return }
followButton.isUserInteractionEnabled = false
let followee = users[indexPath.row]
FollowService.setIsFollowing(!followee.isFollowed, fromCurrentUserTo: followee) { (success) in
defer {
followButton.isUserInteractionEnabled = true
}
guard success else { return }
followee.isFollowed = !followee.isFollowed
self.tableView.reloadRows(at: [indexPath], with: .none)
}
}
}
extension FindFriendsViewController: UISearchBarDelegate {
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
var usernamesArr = [String]()
for user in users {
usernamesArr.append(user.username)
}
searchItem = usernamesArr.filter({$0.lowercased().prefix(searchText.count) == searchText.lowercased()})
searching = true
tableView.reloadData()
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
searching = false
searchBar.text = ""
tableView.reloadData()
}
}

Searchfield and tableview - showing only users with uppercase usernames

I have a searchfield in my app, where users can search for other users. However i have three issues with it:
right now the search only works for users that have a uppercase username. So for instance when i search "Ma", the only user that is showing is "Makelele" because his username has a uppercase letter as the first letter. For instance "mattgilbert" isnt showing at all, even though i should be on the tableview.
when the user has appered in the tableview, the user is still in the tableview, even though i have canceled the search.
i have it so the search for users only begins when the user has typed atleast 2 words, however if a user types more than that into the searchfield the user will just dissapear in the tableview. And i have to search more letters in order for the user to appear again.
It would mean alot if someone could help me out on this, as i have used alot of time on this search stuff. I want it to be as cost effiecent as possible, and at the same time be scaleable (hence why i have this two letters atleast typed before the database runs its query)
This is my code:
class FollowUsersTableViewController: UIViewController {
#IBOutlet var tableView: UITableView!
var isSearching = false
private var viewIsHiddenObserver: NSKeyValueObservation?
let searchController = UISearchController(searchResultsController: nil)
var usersArray = [UserModel]()
var filteredUsers = [UserModel]()
var loggedInUser: User?
//
var databaseRef = Database.database().reference()
//usikker på den koden over
override func viewDidLoad() {
super.viewDidLoad()
searchController.searchBar.delegate = self
//large title
self.title = "Discover"
if #available(iOS 11.0, *) {
self.navigationController?.navigationBar.prefersLargeTitles = true
} else {
// Fallback on earlier versions
}
self.tableView?.delegate = self
self.tableView?.dataSource = self
searchController.searchResultsUpdater = self
searchController.dimsBackgroundDuringPresentation = false
self.searchController.delegate = self;
definesPresentationContext = true
tableView.tableHeaderView = searchController.searchBar
//self.loadProfileData()
//self.searchBar(searchController.searchBar, textDidChange: searchController.searchBar.text)
}
func searchUsers(text: String) {
if text.count >= 2 {
self.usersArray = [] //clear the array each time
let endingText = text + "\u{f8ff}"
databaseRef.child("profile").queryOrdered(byChild: "username")
.queryStarting(atValue: text)
.queryEnding(atValue: endingText)
.observeSingleEvent(of: .value, with: { snapshot in
for child in snapshot.children {
let childSnap = child as! DataSnapshot
print(childSnap)
let userObj = Mapper<UserModel>().map(JSONObject: childSnap.value!)
userObj?.uid = childSnap.key
if childSnap.key != self.loggedInUser?.uid { //ignore this user
self.usersArray.append(userObj!)
}
}
self.tableView.reloadData()
})
}
} //may need an else statement here to clear the array when there is no text
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let dest = segue.destination as! UserProfileViewController
let obj = sender as! UserModel
let dict = ["uid": obj.uid!, "username": obj.username!, "photoURL": obj.photoURL, "bio": obj.bio]
dest.selectedUser = dict as [String : Any]
}
}
// MARK: - tableview methods
extension FollowUsersTableViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return isSearching ? filteredUsers.count : usersArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! FollowTableViewCell
let user = isSearching ? filteredUsers[indexPath.row] : usersArray[indexPath.row]
cell.title?.text = user.username
if let url = URL(string: user.photoURL ?? "") {
cell.userImage?.sd_setImage(with: url, placeholderImage: #imageLiteral(resourceName: "user_male"), options: .progressiveDownload, completed: nil)
cell.userImage.sd_setIndicatorStyle(.gray)
cell.userImage.sd_showActivityIndicatorView()
}
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 50
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.performSegue(withIdentifier: "user", sender: isSearching ? self.filteredUsers[indexPath.row] : self.usersArray[indexPath.row])
}
}
// MARK: - search methods
extension FollowUsersTableViewController:UISearchResultsUpdating, UISearchControllerDelegate, UISearchBarDelegate {
func updateSearchResults(for searchController: UISearchController) {
searchController.searchResultsController?.view.isHidden = false
self.searchUsers(text: self.searchController.searchBar.text!)
filterContent(searchText: self.searchController.searchBar.text!)
self.tableView.reloadData()
}
func filterContent(searchText:String){
if searchText.count >= 2{
self.filteredUsers = self.usersArray.filter{ user in
return(user.username!.lowercased().contains(searchText.lowercased()))
}
}
}
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
isSearching = true
}
func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
isSearching = false
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
isSearching = false
}
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
isSearching = false
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
self.filteredUsers = self.usersArray.filter{ user in
return(user.username!.lowercased().contains(searchText.lowercased()))
}
if(filteredUsers.count == 0){
isSearching = false
} else {
isSearching = true
}
self.tableView.reloadData()
}
}
EDIT: Updated Code
class FollowUsersTableViewController: UIViewController {
#IBOutlet var tableView: UITableView!
var isSearching = false
private var viewIsHiddenObserver: NSKeyValueObservation?
let searchController = UISearchController(searchResultsController: nil)
var usersArray = [UserModel]()
var loggedInUser: User?
//
var databaseRef = Database.database().reference()
//usikker på den koden over
override func viewDidLoad() {
super.viewDidLoad()
searchController.searchBar.delegate = self
//large title
self.title = "Discover"
if #available(iOS 11.0, *) {
self.navigationController?.navigationBar.prefersLargeTitles = true
} else {
// Fallback on earlier versions
}
self.tableView?.delegate = self
self.tableView?.dataSource = self
searchController.searchResultsUpdater = self
searchController.dimsBackgroundDuringPresentation = false
self.searchController.delegate = self;
definesPresentationContext = true
tableView.tableHeaderView = searchController.searchBar
//self.loadProfileData()
//self.searchBar(searchController.searchBar, textDidChange: searchController.searchBar.text)
}
func searchUsers(text: String) {
if text.count >= 2 {
self.usersArray = [] //clear the array each time
let endingText = text + "\u{f8ff}"
databaseRef.child("profile").queryOrdered(byChild: "username")
.queryStarting(atValue: text)
.queryEnding(atValue: endingText)
.observeSingleEvent(of: .value, with: { snapshot in
for child in snapshot.children {
let childSnap = child as! DataSnapshot
print(childSnap)
let userObj = Mapper<UserModel>().map(JSONObject: childSnap.value!)
userObj?.uid = childSnap.key
if childSnap.key != self.loggedInUser?.uid { //ignore this user
self.usersArray.append(userObj!)
}
}
self.tableView.reloadData()
})
}
} //may need an else statement here to clear the array when there is no text
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let dest = segue.destination as! UserProfileViewController
let obj = sender as! UserModel
let dict = ["uid": obj.uid!, "username": obj.username!, "photoURL": obj.photoURL, "bio": obj.bio]
dest.selectedUser = dict as [String : Any]
}
}
// MARK: - tableview methods
extension FollowUsersTableViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return usersArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! FollowTableViewCell
let user = usersArray[indexPath.row]
cell.title?.text = user.username
if let url = URL(string: user.photoURL ?? "") {
cell.userImage?.sd_setImage(with: url, placeholderImage: #imageLiteral(resourceName: "user_male"), options: .progressiveDownload, completed: nil)
cell.userImage.sd_setIndicatorStyle(.gray)
cell.userImage.sd_showActivityIndicatorView()
}
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 50
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.performSegue(withIdentifier: "user", sender: self.usersArray[indexPath.row])
}
}
// MARK: - search methods
extension FollowUsersTableViewController:UISearchResultsUpdating, UISearchControllerDelegate, UISearchBarDelegate {
func updateSearchResults(for searchController: UISearchController) {
searchController.searchResultsController?.view.isHidden = false
self.searchUsers(text: self.searchController.searchBar.text!)
//filterContent(searchText: self.searchController.searchBar.text!)
self.tableView.reloadData()
}
/*
func filterContent(searchText:String){
if searchText.count >= 2{
self.filteredUsers = self.usersArray.filter{ user in
return(user.username!.lowercased().contains(searchText.lowercased()))
}
}
}
*/
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
isSearching = true
}
func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
isSearching = false
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
isSearching = false
self.usersArray = []
self.tableView.reloadData()
}
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
isSearching = false
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
self.usersArray.filter{ user in
return(user.username!.lowercased().contains(searchText.lowercased()))
}
if(usersArray.count == 0){
isSearching = false
} else {
isSearching = true
}
self.tableView.reloadData()
}
}
Please try this It may helps you.
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
let filteredArray = usersArray.filter { ($0["username"] as! String).range(of: searchText!, options: [.diacriticInsensitive, .caseInsensitive]) != nil }
}
It may helps you.Thank you
The answer to question #1
1) right now the search only works for users that have a uppercase
username. So for instance when i search "Ma", the only user that is
showing is "Makelele" because his username has a uppercase letter as
the first letter. For instance "mattgilbert" isnt showing at all, even
though i should be on the tableview.
Firebase doesn't have any kind of uppercase or lowercase search. It just has a literal string query that's case sensitive
The typical solution is to store a 'display' version of your strings and then a 'search' version of your strings were the string is lowercased in code before storing it in Firbease. So for example, here's a users node
users
uid_0
display_name: "Kirk"
search_name: "kirk"
uid_1
display_name: "Spock"
search_name: "spock"
uid_1
display_name: "Montgomery Scott"
search_name: "montgomery scott"
2 when the user has appered in the tableview, the user is still in the
tableview, even though i have canceled the search.
If a search is canceled, the dataSource array should be cleared and your tableView reloaded.
myDataSourceArray = []
self.reloadTableview
3 i have it so the search for users only begins when the user has
typed atleast 2 words, however if a user types more than that into the
searchfield the user will just dissapear in the tableview. And i have
to search more letters in order for the user to appear again.
The code I posted in previous answers solves this and is a complete, tested solution. Please refer back to those answers - you can almost copy and paste the code into a project and it will work.

Firebase - Why isnt search for users working in my app? (updating the searchcontroller when user has typed two letters)

i have had this issue for a long time. The only way my searchUsers function work is when i put it in ViewDidLoad, and then change the .count to be equal or less than 0 (because its 0 by default).
But as it is right now (how i think it should work), the search dosent work.
What i want it to do is :
Only start the firebase search for users when the user has typed at least two letters (so it only searches for the users when the user has started typing, and only showing and loading the relevant data).
Also update the tableview along with filtering the search.
This is my code:
import UIKit
import FirebaseDatabase
import Firebase
import SDWebImage
import ObjectMapper
class FollowUsersTableViewController: UIViewController {
#IBOutlet var tableView: UITableView!
private var viewIsHiddenObserver: NSKeyValueObservation?
let searchController = UISearchController(searchResultsController: nil)
var usersArray = [UserModel]()
var filteredUsers = [UserModel]()
var loggedInUser: User?
//
var databaseRef = Database.database().reference()
//usikker på den koden over
override func viewDidLoad() {
super.viewDidLoad()
//large title
self.title = "Discover"
if #available(iOS 11.0, *) {
self.navigationController?.navigationBar.prefersLargeTitles = true
} else {
// Fallback on earlier versions
}
self.tableView?.delegate = self
self.tableView?.dataSource = self
searchController.searchResultsUpdater = self
searchController.dimsBackgroundDuringPresentation = false
self.searchController.delegate = self;
definesPresentationContext = true
tableView.tableHeaderView = searchController.searchBar
//self.loadProfileData()
//self.searchBar(searchController.searchBar, textDidChange: searchController.searchBar.text)
}
func searchUsers(text: String) {
if text.count >= 2 {
self.usersArray = [] //clear the array each time
let endingText = text + "\u{f8ff}"
databaseRef.child("profile").queryOrdered(byChild: "username")
.queryStarting(atValue: text)
.queryEnding(atValue: endingText)
.observeSingleEvent(of: .value, with: { snapshot in
for child in snapshot.children {
let childSnap = child as! DataSnapshot
print(childSnap)
let userObj = Mapper<UserModel>().map(JSONObject: childSnap.value!)
userObj?.uid = childSnap.key
if childSnap.key != self.loggedInUser?.uid { //ignore this user
self.usersArray.append(userObj!)
}
}
self.tableView.reloadData()
})
}
} //may need an else statement here to clear the array when there is no text
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let dest = segue.destination as! UserProfileViewController
let obj = sender as! UserModel
let dict = ["uid": obj.uid!, "username": obj.username!, "photoURL": obj.photoURL, "bio": obj.bio]
dest.selectedUser = dict as [String : Any]
}
}
// MARK: - tableview methods
extension FollowUsersTableViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return searchController.searchBar.text!.count >= 2 ? filteredUsers.count : 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! FollowTableViewCell
let user = filteredUsers[indexPath.row]
cell.title?.text = user.username
if let url = URL(string: user.photoURL ?? "") {
cell.userImage?.sd_setImage(with: url, placeholderImage: #imageLiteral(resourceName: "user_male"), options: .progressiveDownload, completed: nil)
cell.userImage.sd_setIndicatorStyle(.gray)
cell.userImage.sd_showActivityIndicatorView()
}
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 50
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.performSegue(withIdentifier: "user", sender: self.filteredUsers[indexPath.row])
}
}
// MARK: - search methods
extension FollowUsersTableViewController:UISearchResultsUpdating, UISearchControllerDelegate, UISearchBarDelegate {
func searchBar(_ searchBar: UISearchBar,
textDidChange searchText: String) {
self.searchUsers(text: searchText)
}
func updateSearchResults(for searchController: UISearchController) {
searchController.searchResultsController?.view.isHidden = false
filterContent(searchText: self.searchController.searchBar.text!)
self.tableView.reloadData()
}
func filterContent(searchText:String){
if searchText.count >= 2{
self.filteredUsers = self.usersArray.filter{ user in
return(user.username!.lowercased().contains(searchText.lowercased()))
}
}
}
}
You need to set
searchController.searchBar.delegate = self
You conform to UISearchResultsUpdating and implement updateSearchResults but it doesn't call func searchUsers(text: String)
and conform to UISearchControllerDelegate that has no relation to the search look to it's methods Here

Search bar filtering wrong data

Disparately asking for your assistance
I am trying to filter Table View using search bar but the data I am getting is not in the correct position,
I tried several times to figure it out but without any chance, the result I am getting is only the first row does not matter which Room Number I am typing
I pasted the code below, your assistance is highly appreciated
final let urlString = "http://ccm-hotels.com/ccmandroid/api/getteams.php"
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var searchBar: UISearchBar!
#IBAction func BackToMenu(_ sender: UIBarButtonItem) {
let MainMenu = self.storyboard?.instantiateViewController(withIdentifier: "MainMenu") as! MainMenu
self.navigationController?.pushViewController(MainMenu, animated: true)
}
var openCaseRoomArray: [String] = []
var openCaseNameArray: [String] = []
var openCaseRoomArrayF: [String] = []
var inSearchMode = false
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
searchBar.delegate = self
searchBar.returnKeyType = UIReturnKeyType.done
openCaseRoomArrayF = openCaseRoomArray
let alertController = UIAlertController(title: nil, message: "Please wait\n\n", preferredStyle: .alert)
let spinnerIndicator = UIActivityIndicatorView(activityIndicatorStyle: .whiteLarge)
spinnerIndicator.center = CGPoint(x: 135.0, y: 65.5)
spinnerIndicator.color = UIColor.black
spinnerIndicator.startAnimating()
alertController.view.addSubview(spinnerIndicator)
self.present(alertController, animated: false, completion: nil)
let when = DispatchTime.now() + 5
DispatchQueue.main.asyncAfter(deadline: when){
// your code with delay
alertController.dismiss(animated: true, completion: nil);}
self.downloadJsonWithURL()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func downloadJsonWithURL() {
let url=URL(string:"http://ccm-hotels.com/ccmandroid/api/getteams.php")
do {
let allContactsData = try Data(contentsOf: url!)
let allContacts = try JSONSerialization.jsonObject(with: allContactsData, options: JSONSerialization.ReadingOptions.allowFragments) as! [String : AnyObject]
if let arrJSON = allContacts["CurrentOpenCases"] {
for index in 0...arrJSON.count-1 {
let aObject = arrJSON[index] as! [String : AnyObject]
if let Room = aObject["RoomNumber"] as? String {
openCaseRoomArray.append(Room)
}
if let Name = aObject["GuestName"] as? String {
openCaseNameArray.append(Name)
}
}
}
self.tableView.reloadData()
}
catch {
}
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if inSearchMode {
return openCaseRoomArrayF.count
}
return openCaseRoomArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! TableViewCell
if inSearchMode {
cell.openCaseRoom.text = self.openCaseRoomArrayF[indexPath.row]
cell.openCaseName.text = self.openCaseNameArray[indexPath.row]
}else{
cell.openCaseRoom.text = self.openCaseRoomArray[indexPath.row]
cell.openCaseName.text = self.openCaseNameArray[indexPath.row]
}
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let vc = self.storyboard?.instantiateViewController(withIdentifier: "DetailViewController") as! DetailViewController
vc.dopenCaseRoomString = openCaseRoomArray[indexPath.row]
vc.openCaseNameString = openCaseNameArray[indexPath.row]
self.navigationController?.pushViewController(vc, animated: true)
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
if searchBar.text == nil || searchBar.text == "" {
inSearchMode = false
view.endEditing(true)
tableView.reloadData()
} else {
inSearchMode = true
openCaseRoomArrayF = openCaseRoomArray.filter({$0 == searchBar.text})
tableView.reloadData()
}
}
}
In your func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell method you are showing name from self.openCaseNameArray while you are updating your search result in self.openCaseRoomArrayF. When you are getting the api response you are assigning room and its corresponding name in your two arrays but when you are searching and updating your search result in self.openCaseRoomArrayF the index get changed. Now openCaseNameArray and openCaseRoomArray are in matched index but openCaseNameArray and openCaseRoomArrayF are not in same matched index. So you will not get the corresponding name in openCaseNameArray if you take room from openCaseRoomArrayF.
Try to make a Class (e.g Room) and store Room class object in a array. Search and show from that array. No need to maintain to array for this.

searchBar filtered tableViewCells didSelectItemAt indexPath display in navigationBar Title

enter image description hereI am having trouble implementing a didSelectRowAtIndexPath from a searchBar filtered tableView cell. When I update the tableView list based on searchbar textDidChange, and perform a show segue to another ViewController, the navigationBar Title is always displaying the non-filtered tableViews indexPath 0. In other words, I would like to have the navigation title display the text from the didSelectAtIndex of search results tableView (not the original indexPath cell text from the non-filtered tableView). Hopefully that makes sense, and thanks in advance!
// viewDidLoad method
override func viewDidLoad() {
super.viewDidLoad()
searchBar.searchBarStyle = UISearchBarStyle.prominent
searchBar.placeholder = " Search Places..."
searchBar.sizeToFit()
searchBar.isTranslucent = false
searchBar.backgroundImage = UIImage()
searchBar.delegate = self
searchBar.returnKeyType = UIReturnKeyType.done
navigationItem.titleView = searchBar
ref = FIRDatabase.database().reference()
fetchPlaces()
placesClient = GMSPlacesClient.shared()
locationManager.requestAlwaysAuthorization()
tableView.allowsMultipleSelectionDuringEditing = true
}
var placeList = [Place]()
var placesDictionary = [String: Place]()
// fetch places for tableView method
func fetchPlaces() {
let uid = FIRAuth.auth()?.currentUser?.uid
let ref = FIRDatabase.database().reference().child("users").child(uid!).child("Places")
ref.observe(.childAdded, with: { (snapshot) in
if let dictionary = snapshot.value as? [String: AnyObject] {
let place = Place()
place.setValuesForKeys(dictionary)
if let addedBy = place.addedBy {
self.placesDictionary[addedBy] = place
self.placeList.insert(place, at: 0)
}
//this will crash because of background thread, so lets call this on dispatch_async main thread
DispatchQueue.main.async(execute: {
self.tableView.reloadData()
})
}
}, withCancel: nil)
}
// search variables
lazy var searchBar:UISearchBar = UISearchBar()
var isSearching = false
var filteredData = [Place]()
// searchBar method
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
if searchBar.text == nil || searchBar.text == "" {
isSearching = false
view.endEditing(true)
tableView.reloadData()
} else {
isSearching = true
filteredData = placeList.filter({$0.place?.range(of: searchBar.text!) != nil})
tableView.reloadData()
}
}
// tableView methods
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if isSearching {
return filteredData.count
}
return placeList.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .subtitle, reuseIdentifier: cellId)
if isSearching {
cell.textLabel?.text = filteredData[indexPath.row].place
} else {
cell.textLabel?.text = placeList[indexPath.row].place
}
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let placeDetailsVC = CurrentUserPlaceDetailsVC()
if isSearching == false {
placeDetailsVC.navigationTitle = placeList[(indexPath.row)].place
show(placeDetailsVC, sender: self)
} else {
placeDetailsVC.navigationTitle = filteredData[(indexPath.row)].place
show(placeDetailsVC, sender: self)
}
}
}
Create a string in your up coming ViewController.
class CurrentUserPlaceDetailsVC: UIViewController {
var navigationTitle: String?
override func viewDidLoad(){
super.viewDidLoad()
self.navigationItem.title = navigationTitle
}
}
Now instead of assigning the title directly to navigationBar you should assign it first to that string and then to navigationBar in viewDidLoad method of your viewController.
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let placeDetailsVC = CurrentUserPlaceDetailsVC()
// Get Cell Label
placeDetailsVC.navigationTitle = placeList[indexPath.row].place
show(placeDetailsVC, sender: self)
}