edit: I solved the problem by uncommenting searchBar delegate in viewDidLoad. Thank you
I'm working on a project on using realm. But my problem is when i search the items with this code below it doesn't make any filter and all i see is all the items not the ones i search.
func loadItems() {
todoItems = selectedCategory?.items.sorted(byKeyPath: "title", ascending: true)
tableView.reloadData()
}
}
//MARK: - Search Bar Methods
extension ToDoListViewController: UISearchBarDelegate {
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
if searchBar.text == "" {
loadItems()
DispatchQueue.main.async {
searchBar.resignFirstResponder()
}
}else{
todoItems = todoItems?.filter("title CONTAINS[cd] %#", searchBar.text!).sorted(byKeyPath: "dateCreated", ascending: true)
tableView.reloadData()
}
}
}
Related
extension TableViewController: UISearchBarDelegate {
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
searchedPets = PetsList.filter { $0.lowercased().prefix(searchText.count) == searchText.lowercased() }
//.uppercased()
searching = true
TableView.reloadData()
}
I am trying to filter my array in my tableview to "contains" instead of "prefix" when searching.
Here is my code:
var searching = false
var cityArray = [["NYC, NY, New Hampshire"], ["Buffalo, NY"]]
func reloadData() {
tableview.reloadData()
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
searching = true
searchCity = cityArray.flatMap({ $0 }).filter ({
$0.lowercased().contains(searchBar.text!.lowercased())})
reloadData()
}
This function successfully does this. However, when I stop editing in the search bar, the tableview becomes blank without values and does not return the previous array prior to searching.
My Previous version of prefix allowed me to return the previous array no problem:
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
searching = true
searchCity = cityArray.flatMap({ $0 }).filter { $0.lowercased().prefix(searchText.count) ==
searchText.lowercased()}
reloadData()
}
You’ve changed to using searchBar.text rather than searchText.
The following should resolve your issue (not tested):
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
searching = true
searchCity = cityArray.flatMap({ $0 }).filter ({
$0.lowercased().contains(searchText.lowercased())})
reloadData()
}
You have to set searching to false if searchText is empty.
And range(of with caseInsensitive option is more efficient than the manual lowercased conversion
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
if searchText.isEmpty {
searching = false
searchCity.removeAll()
} else {
searching = true
searchCity = cityArray.flatMap({ $0 })
.filter{ $0.range(of: searchText, options: .caseInsensitive) != nil }
}
reloadData()
}
To solve this I used the answers from above and meshed them together:
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
if searchText.isEmpty {
print("search Text is nil")
searching = false
} else {
searching = true
searchCity = cityArray.flatMap({ $0 }).filter ({
$0.lowercased().contains( searchText.lowercased())})
}
reloadData()
}
I have a SearchBar when i press the cancel button i have it set so that the textfield should have no text and all of my collection view cell's show
When the cancel button is tapped while there is still text in the TextField my collection view shows no cells until i go back into the search bar and press the delete button "X"
Would appreciate some help Thanks
Here is the code
print(" search button pressed")
navigationItem.titleView = searchBar
searchBar.searchTextField.backgroundColor = .black
searchBar.searchTextField.textColor = .white
searchBar.placeholder = "search for a contact"
searchBar.showsCancelButton = true
searchBar.becomeFirstResponder()
navigationItem.leftBarButtonItem = nil
navigationItem.rightBarButtonItem?.tintColor = .white
} else {
print(" cancel button pressed")
searchBar.searchTextField.text? = ""
navigationItem.titleView = nil
searchBar.showsCancelButton = false
navigationItem.rightBarButtonItem?.isEnabled = true
navigationItem.rightBarButtonItem?.tintColor = .purple
collectionView.reloadData()
Did you try assigning nil to searchBar.searchTextField.text? Maybe that can make a difference.
here's how I would check if I've done my implementation properly. Make sure I'm calling necessary delegate methods for UISearchBarDelegate and handle filter there.
extension MyViewController: UISearchBarDelegate {
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
searchBar.showsCancelButton = true
}
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
self.view.endEditing(true)
if (searchBar.text?.count)! > 0 {
searchHandler(searchText: searchBar.text!)
}
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
searchBar.text = ""
searchBar.showsCancelButton = false
self.view.endEditing(true)
filteredValues?.removeAll() // this removes any previous array items
filteredValues = listValues // this assigns your listValues to filteredValues
collectionView?.reloadData() // this reloads your collectionView
}
func searchBar(_ searchBar: UISearchBar, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
if (searchBar.text?.count)! > 0 {
searchHandler(searchText: searchBar.text!)
}
return true
}
func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
searchHandler(searchText: searchText)
}
fileprivate func searchHandler(searchText: String) {
//implement your filtering here
}
}
Again, there are different ways you can implement your search filtering and assign your filtered values to the collectionView data source.
Hope this helps. Thanks
I have an array like ["apple","appear","Azhar","code","BCom"] etc. This array contain more than half a million of records.
Now what I want to do, is to place a UISearchBar like in google and then whenever user types a text, then the dropdown list would appear with all the results containing this text and user could select one from the list.
For example - if the user types "a", then "apple","appear" and "Azhar" would appear in a drop-down list.
I don't want to use a UITableView or anything else to load the records. Whenever user types any word it should collect records from the array and make a drop down to display them.
How can I do this?
Suggestions required please.
Pretty simple code that would do the trick, the search bar filter is easy, as for the drop down menu i use a third party Pod named 'DropDown' that is very easy to use : https://github.com/AssistoLab/DropDown
import UIKit
import DropDown
class ViewController: UIViewController, UISearchBarDelegate {
var data: [String] = ["apple","appear","Azhar","code","BCom"]
var dataFiltered: [String] = []
var dropButton = DropDown()
#IBOutlet weak var searchBar: UISearchBar!
override func viewDidLoad() {
super.viewDidLoad()
dataFiltered = data
dropButton.anchorView = searchBar
dropButton.bottomOffset = CGPoint(x: 0, y:(dropButton.anchorView?.plainView.bounds.height)!)
dropButton.backgroundColor = .white
dropButton.direction = .bottom
dropButton.selectionAction = { [unowned self] (index: Int, item: String) in
print("Selected item: \(item) at index: \(index)") //Selected item: code at index: 0
}
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
dataFiltered = searchText.isEmpty ? data : data.filter({ (dat) -> Bool in
dat.range(of: searchText, options: .caseInsensitive) != nil
})
dropButton.dataSource = dataFiltered
dropButton.show()
}
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
searchBar.setShowsCancelButton(true, animated: true)
for ob: UIView in ((searchBar.subviews[0] )).subviews {
if let z = ob as? UIButton {
let btn: UIButton = z
btn.setTitleColor(UIColor.white, for: .normal)
}
}
}
func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
searchBar.showsCancelButton = false
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
searchBar.resignFirstResponder()
searchBar.text = ""
dataFiltered = data
dropButton.hide()
}
}
when I perform a search in the search bar while the view is loading( loading the data from server) I get error that auxiliar is nil.
var isSearch = false
var auxiliar : [Shops]!
var searchActive: Bool = false
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if searchActive
{
return auxiliar.count
}
return shops.count
}
the data comes in JSON to the TableView
here is when I assign auxiliar
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
auxiliar = shops.filter { $0.shopname.range(of: searchText, options: .caseInsensitive, range: nil, locale: nil) != nil}
if searchText == "" || searchBar.text == nil {
auxiliar = shops
}
tableView.reloadData()
}
Declare auxiliar as an empty array.
var auxiliar = [Shops]()
When auxiliar.count is accessed by tableView(_:, numberOfRowsInSection:), the tableView will be empty. Then, when you get the data and searchBar(_:,textDidChange:) is called, auxiliar is set again. When you reload the table, the new data is displayed.